Hi Alex
I had an appointment canceled this afternoon, so I took the opportunity to engage a bit more the code in the challenge.
As you mentioned I should not invest too much time...
Two hours+ in, while I tried to reason about the right amount of pragmatism and "state-of-the-artness" (should it just work? should it show I care?) I realized that writing something that will leave my mind at peace will eat me a whole day if not more. If you like I can do that, probably on Sunday as I mentioned. But as suppose you are not interested in every detail or perfect solution, but mostly on how I would go about tacking the most important pain points of the challenge. So, I will describe how I would finish the challenge, and then you can decide if it is enough for a follow up conversation or if I should actually get the thing done.
There is a pseudo code as a draft in this PR:
TaskService#createwould publish the TaskCreated event with the task id.- The
EventManagerwould then broadcast the message to all the subscribed actions (Yes, IActiveSupport::Notificationscould be used here, as far as I understood, but I would probably wrap it in an adapter), or I would just plug something I am more familiar with, like this gem I wrote. - The subscriber of
TaskCreatedwould callTaskNotificationWebhookWorker.perform_async('event_name', { id: 'task-id' }). That would be a sidekiq worker that would perform the notification on each webhook as a background job. Actually, it would not do the job itself, but it would delegate the job to a non-worker service (TaskWebhooksService, perhaps). The reason for the background job is that waiting for all the webhooks to be reached can take long and failures may occur (timeout, service unavailable, application error). - The TaskWebhooksService#notify(event_name, payload) would do the job of sending the request to the webhooks.
- Same for every other event
What must be considered:
- What happens if a http request to a webhook fails? Do we want to retry? How many times?
- How do we make sure that each webhook is notified only once per event if the same event is retired? I think we need to implement a queue of notifications to be sent out and their respective status (pending, failed, done)
- Also, the delete event is tricky to handle, because when a task is deleted we cannot figure out what is the organization that onwed that task, unless we do something like:
- soft delete
- pass the organization id to the TaskDeleted
- delay the deletion until all the events are processed and all the webhooks are notified
Naming is difficult, I go back and forth with some names for services and workers.
I think this summarizes.
Looking forward to hearing from you.
Task service publishes the task_deleted/created/updated events along with the task Id. Yeah, ActiveSupport::Notifications could be used, but I were to write the
Of course what I am describing next would be over engineering if that was a prototype I had to rollout over the weekend, but if I was starting a project that matters...
Of course the level of pragmatism would increase had I had to rollout the project
Maybe you can take a look if what you see is
- https://github.com/mjacobus/koine-event-manager
- https://github.com/mjacobus/nurse-rb
- hanami/model#240 (comment)
Projections Processors https://api.rubyonrails.org/classes/ActiveSupport/Notifications.html