July 25, 2015

Recipe Architecture, Part 2

After sleeping on the recipe architecture (I'm a big believer in hammock driven development), here's the plan.

Client->Server Middleware

Some of the client handlers will have middleware, which will dispatch the event to the server through sente.They'll send along a token that will authorize the user as a given UID.

Server Handler

On the server, a handler will take this event, plus the client UID. Server handlers are different than client handlers. Client handlers may have side effects, but their primary job is to return a new version of the database. Server handlers, on the other hand, do two things: side effects, and dispatching new events to the client.

I won't be using the reply-fn functionality of Sente, because I want to keep all event logic in one place. When data comes in from the server, I want it to be handled exactly the same way as any other event.

Validation Logic

Reader conditionals will allow us to share some (but not all) validation logic between the server and the client handlers.

Server->Client Dispatcher

I want to be able to do:

;; notify the client that a recipe was received
(dispatch [:recipe/received    {:recipe {:id 1234 :title ...}}])

;; notify the client that we're making progress on some long-running task
(dispatch [:progress-report    {:some :data :goes :here}])

;; notify the client of success or failure in adding a recipe
(dispatch [:recipe/add-failure {:error ["recipe is stupid"] :recipe {:id 1234 :title ... }}])
(dispatch [:recipe/add-success {:recipe {:id 1234 :title ... }}])

On the client ...

Besides the middleware, everything else is just re-frame.

Undo

On one hand, maybe we can just not support undo. But that's pretty lame. The other possibility is something like writing an undo handler on the client that figures out what changed and tells the server. Why not do all client->server notifications this way? Because it's hard, and I can do it later, and doing the diff will be expensive for large client states so we don't want to make all state changes more expensive across the board, in case we end up having some small state updates every 16ms or something.

Tags: recipe-app