The piece of software I'm writing operates on the following object types:
These objects can be linked together, and each of them contains some additional information. For example, a Call contains the caller number, an Agent contains it's name, and so on.
This model should react to external events delivered through a message queue. Most of the events are like the following:
- an Agent has joined a CallQueue;
- an Agent has left a CallQueue;
- a Call was added to a CallQueue;
- a Call has left a CallQueue;
- an Agent has answered a Call;
- an Agent has completed a Call;
And so on. Basically, most of the events trigger creation and removal of links between the objects - and also contain additional information. Some events trigger additional business logic, which is outside of the scope of this question.
Updates of Agents, Calls and CallQueues should be observed from outside for scenarios like these:
- delivering application state updates to clients through event streams (e.g. over WebSockets);
- persisting updates to a database;
Un update is an event which is raised when either the object's data has changed, or a link to another object was created or removed.
What are the best practices to organize business logic? Options that I have:
Make a separate component for handling each type of object, e. g.
CallQueuesRegistry. When, for example, an agent-linked-to-call-queue event happens, catch it in the
CallQueuesRegistry, create a link and notify the
AgentsRegistry, so that both of them execute their business logic. Expose update event streams from each component to the outside world, so that persistance and WebSockets handlers can bind to it and react.
Make a single
ApplicationStatecomponent for handling all kinds of events. Process links updates internally. Try to separate business logic into private methods. Expose a single update event stream from the component to the outside world.
A mix of the two above: hide separate components behind an
ApplicationStateobject, which should react to the events and act as a conductor for type-specific business logic.
Put business logic into Agents, Calls and CallQueues - I can hardly envision this kind of approach when Dependency Injection comes into play, and additional components should be used. Also, it is unclear to me which object should react to an agent-has-answered-a-call event: the Agent or the Call.
Which option is preffered and why? What other options exist?
EDIT: split the question in two, renamed Queues to CallQueues.
EDIT 2: Clarification: a
CallQueue is generally a list of calls waiting to be processed by an
Agent who is bound to that particular
CallQueue. It is a virtual representation of a real
queue in an external application, and it has nothing to do with a
queue data structure, because the FIFO logic is managed in that external app. My app only gets notifications about a certain call entering the queue, leaving it (which can happen randomly) or making all the way to a free
Agent and getting connected with it. Multiple
There is no such thing as a queue of
Agents waiting for a
Call, at least in the scope of this app. As far as we're concerned, a pseudo-random free
Agent connects to a pseudo-random
Call form the