component

2016-06-15T18:53:18.000012Z

Are there any discussions/blog-posts that talk about making a component fault tolerant? What happens if my database goes down, or isn’t up, and I want to defer startup until after the connection is available and working?

2016-06-15T18:55:33.000013Z

or halt a component and restart when the connection is available again

seancorfield 2016-06-15T18:59:46.000014Z

How would you handle dependencies in general on a component restart?

seancorfield 2016-06-15T19:00:24.000015Z

If you restart your db component, what about components that depend on it? Should they all be restarted too?

2016-06-15T19:02:13.000016Z

I might have my answer

seancorfield 2016-06-15T19:02:15.000017Z

I think an individual app can decide what to do in situations like these but I don't think Component itself can.

2016-06-15T19:02:48.000018Z

Hmm… I need to rethink

2016-06-15T19:03:10.000019Z

I shouldn’t be failing to start just because the real DB isn’t available.

2016-06-15T19:03:40.000020Z

I should gracefully report an error, and keep functioning…

seancorfield 2016-06-15T19:07:33.000021Z

For our Component-based apps, if the db is not available at startup, we'd want to fail hard.

seancorfield 2016-06-15T19:08:20.000022Z

If the db goes offline while we're running, that's a different issue but some of our processes should just die at that point.

2016-06-15T19:09:07.000023Z

I’m using docker and docker-compose… and the db starts slowly

2016-06-15T19:10:49.000024Z

I think I can solve it there, but I was trying to come up with a solution because if I grow this and break the services across multiple cloud instances, then network route drops might play a role and I’d want the “components” which face external services to tolerate interruption

seancorfield 2016-06-15T19:11:17.000025Z

So your app would need to maintain mutable state in the components to indicate whether they are "ready".

2016-06-15T19:12:31.000026Z

when not ready respond thus to requests (50x) and poll in the background for availability and then bring myself back online.

2016-06-15T19:13:05.000027Z

I’m wondering if I should have a coordinator service external that can bring stuff up and down. Like a service in docker, that sends docker commands to stop and start stuff...

2016-06-15T19:14:44.000028Z

Hmmm… I could add a ring handler to report status and then post to the same url to do a restart…

donaldball 2016-06-15T19:29:12.000029Z

I have two pieces that solve this problem for me

donaldball 2016-06-15T19:30:01.000030Z

I have a boot fn which combines building and starting a system and, if it gets errors thrown starting the database too many times, will reconfigure and start the system with the database disabled

donaldball 2016-06-15T19:30:28.000031Z

I also have a manager wrapping my system that watches for config changes and restarts the system during a safe period

2016-06-15T19:32:01.000032Z

I like that. I’ve been thinking about building an application infrastructure that watches a datastore (git repo + config files) for changes, and triggers behaviors off of it. While being able to poll services (watch statistics) and respond to certain behaviors (if I have a defined response) or just report on that state through some notification (email/text/slack)

2016-06-15T19:33:18.000033Z

thx donald and sean

seancorfield 2016-06-15T19:34:49.000034Z

Yeah, if you have an app that can run in both "connected" and "disconnected" mode, that pretty much has to be baked into your logic from the get-go. I don’t think there’s much support a generic library can provide you with there (other than provide structure around your "state").

donaldball 2016-06-15T19:34:50.000035Z

If my system were under any real load, I’d like to build a piece that triggers config changes on exception rate and/or timeouts

2016-06-15T19:34:58.000036Z

Internal/External message queues might handle some of this also in a more tolerant way

seancorfield 2016-06-15T19:35:10.000037Z

☝️:skin-tone-2:

2016-06-15T19:35:21.000038Z

really been thinking about that

seancorfield 2016-06-15T19:35:23.000039Z

We’re in the process of switching architectures to that approach.

roberto 2016-06-15T19:35:47.000040Z

doesn’t netflix have a database driver that helps with that?

2016-06-15T19:36:22.000041Z

in the end I want to be able to break apart a message request and compose it from the results of many different services, that’s going to require some type of queue pipelining functionality.

donaldball 2016-06-15T19:38:18.000043Z

I have my web handlers describe the services on which they depend and respond automatically with 503s when they aren’t available

2016-06-15T19:42:24.000044Z

Might be able to use a core.async channel to say “go” to the next component when it’s dependencies are ready...

roberto 2016-06-15T19:49:31.000045Z

ah, so you have a channel that is passed in as a dependency, and the components are pushed to that channel when you want to “scale” or “replace” ?

2016-06-15T20:04:42.000046Z

I was thinking that if I’m dependent, my start doesn’t get called until the previous component publishes “ready” to a channel it returns… then I’m free to go ahead

2016-06-15T20:05:16.000047Z

IT’s an async callback like a promise done clojure’s way

2016-06-15T20:05:43.000048Z

I do a lot of javascript that way, where I return a deferred instead of a result, and you trigger when I comeback. My templates render that way a lot.

2016-06-15T20:07:29.000049Z

My component’s start function doesn’t get called until all deps have declared that they are “ready"

donaldball 2016-06-15T20:08:08.000050Z

That’s the way component’s systems work now, except without the asynchrony

2016-06-15T20:08:38.000051Z

exactly

2016-06-15T20:11:22.000052Z

My only problem is when the database comes up I check to verify/run the database table migrations (ragtime) and my own internal data-migration functions executed. before the component says it’s ready to be used, and that requires the connection to be active, which requires blocking

2016-06-15T20:12:39.000053Z

I’m using wait-for-it.sh to block until the database server is running in my docker-compose config file, but that’s not as robust as doing something in my server code to be more tolerant of dropped connections.

2016-06-15T20:13:00.000054Z

I just tested and deployed that while we’re chatting and it seems to be fine

seancorfield 2016-06-15T20:13:24.000055Z

Sounds like you need something in your -main function that handles that prior to creating & starting the application’s Component?

2016-06-15T20:14:49.000056Z

Maybe, I might have to duplicate the config code and block until the database connection is present.

2016-06-15T20:16:29.000057Z

Maybe I do something else on my own with channels in my start function for my component instead...

2016-06-15T20:19:38.000058Z

I could do what I said myself apart from system through the system map I think. Put a channel behind a key, and defer my web service from coming up until after the database connection is finished. That’s the solution for the existing architecture. Thanks for helping me think this through guys.

roberto 2016-06-15T20:24:09.000059Z

let us know how it works out. I’m very interested in this.

roberto 2016-06-15T20:24:42.000060Z

I’m having a similar challenge with components that hold tokens to third party services that expire after a certain time, and need to get refreshed.

donaldball 2016-06-15T20:28:22.000061Z

Heh I just solved a similar problem thereby myself. My case is an internal keyring whose keys need to be rotated periodically.

donaldball 2016-06-15T20:28:51.000062Z

Currently I have a worker go loop that starts when the component starts, stops when the component stops, and the keyring state is maintained in an atom

donaldball 2016-06-15T20:29:26.000063Z

go loops and component lifecycle fns are a nice fit

2016-06-15T21:03:34.000064Z

That’s great to hear

2016-06-15T21:04:06.000065Z

especially since async channels are essentially queues so they fit with other models I want to use, like websockets and Message Queues.