Example #1
0
        public void AddWaitingWorker_UnknownWorker_ShouldReturnAddToWaitingAndKnownWorkers()
        {
            var service = new Service("service");
            var worker = new Worker("W001", new NetMQFrame("W001"), service);

            service.AddWaitingWorker(worker);

            Assert.That(service.WaitingWorkers.Count(), Is.EqualTo(1));
            Assert.That(service.DoWorkersExist(), Is.True);
        }
Example #2
0
        /// <summary>
        /// Adds a worker to the waiting worker list and if it is not known it adds it to the known workers as well
        /// </summary>
        /// <param name="worker">the worker to add</param>
        public void AddWaitingWorker(Worker worker)
        {
            if (!IsKnown (worker))
                m_workers.Add (worker);

            if (!IsWaiting (worker))
            {
                // add to the end of the list
                // oldest is at the beginning of the list
                m_waitingWorkers.Add (worker);
            }
        }
Example #3
0
        public void DeleteWorker_KnownWorker_ShouldReturnAddToWaitingAndKnownWorkers()
        {
            Worker workerToDelete = null;
            var service = new Service("service");

            for (var i = 0; i < 10; i++)
            {
                var id = $"W0{i:N3}";
                var worker = new Worker(id, new NetMQFrame(id), service);

                if (i == 5)
                    workerToDelete = worker;

                service.AddWaitingWorker(worker);
            }

            Assert.That(service.WaitingWorkers.Count(), Is.EqualTo(10));
            Assert.That(service.DoWorkersExist(), Is.True);

            service.DeleteWorker(workerToDelete);

            Assert.That(service.WaitingWorkers.Count(), Is.EqualTo(9));
        }
Example #4
0
        /// <summary>
        ///     sends a message to a specific worker with a specific command 
        ///     and add an option option
        /// </summary>
        private void WorkerSend (Worker worker, MDPCommand command, NetMQMessage message, string option = null)
        {
            var msg = message ?? new NetMQMessage ();

            // stack protocol envelope to start of message
            if (!ReferenceEquals (option, null))
                msg.Push (option);

            msg.Push (new[] { (byte) command });
            msg.Push (MDPWorkerHeader);
            // stack routing envelope
            var request = Wrap (worker.Identity, msg);

            DebugLog (string.Format ("Sending {0}", request));
            // send to worker
            Socket.SendMessage (request);
        }
Example #5
0
        /// <summary>
        ///     removes the worker from the known worker list and
        ///     from the service it refers to if it exists and
        ///     potentially from the waiting list therein
        /// </summary>
        /// <param name="worker"></param>
        private void RemoveWorker (Worker worker)
        {
            if (m_services.Contains (worker.Service))
            {
                var service = m_services.Find (s => s.Equals (worker.Service));
                service.DeleteWorker (worker);

                DebugLog (string.Format ("removed worker {0} from service {1}",
                                         worker.Id,
                                         service.Name));
            }

            m_knownWorkers.Remove (worker);

            DebugLog (string.Format ("removed {0} from known worker.", worker.Id));
        }
Example #6
0
        /// <summary>
        ///     adds the worker to the service and the known worker list
        ///     if not already known
        ///     it dispatches pending requests for this service as well
        /// </summary>
        private void AddWorker (Worker worker, Service service)
        {
            worker.Expiry = DateTime.UtcNow + m_heartbeatExpiry;

            if (!m_knownWorkers.Contains (worker))
            {
                m_knownWorkers.Add (worker);

                DebugLog (string.Format ("added {0} to known worker.", worker.Id));
            }

            service.AddWaitingWorker (worker);

            DebugLog (string.Format ("added {0} to waiting worker in service {1}.",
                                     worker.Id,
                                     service.Name));

            // get pending messages out
            ServiceDispatch (service, null);
        }
Example #7
0
        /// <summary>
        ///     process a READY, REPLY, HEARTBEAT, DISCONNECT message sent to the broker by a worker
        /// </summary>
        /// <param name="sender">the sender identity frame</param>
        /// <param name="message">the message sent</param>
        public void ProcessWorkerMessage ([NotNull] NetMQFrame sender, [NotNull] NetMQMessage message)
        {
            // should be 
            // READY        [mdp command][service name]
            // REPLY        [mdp command][client adr][e][reply]
            // HEARTBEAT    [mdp command]
            if (message.FrameCount < 1)
                throw new ApplicationException ("Message with too few frames received.");

            var mdpCommand = message.Pop ();                // get the mdp command frame it should have only one byte payload

            if (mdpCommand.BufferSize > 1)
                throw new ApplicationException ("The MDPCommand frame had more than one byte!");

            var cmd = (MDPCommand) mdpCommand.Buffer[0];    // [service name] or [client adr][e][reply]
            var workerId = sender.ConvertToString ();       // get the id of the worker sending the message
            var workerIsKnown = m_knownWorkers.Any (w => w.Id == workerId);

            switch (cmd)
            {
                case MDPCommand.Ready:
                    if (workerIsKnown)
                    {
                        // then it is not the first command in session -> WRONG
                        // if the worker is know to a service, remove it from that 
                        // service and a potential waiting list therein
                        RemoveWorker (m_knownWorkers.Find (w => w.Id == workerId));

                        Log (string.Format ("READY out of sync. Removed worker {0}.", workerId));
                    }
                    else
                    {
                        // now a new - not know - worker sent his READY initiation message
                        // attach worker to service and mark as idle - worker has send READY as first message
                        var serviceName = message.Pop ().ConvertToString ();
                        var service = ServiceRequired (serviceName);
                        // create a new worker and set the service it belongs to
                        var worker = new Worker (workerId, sender, service);
                        // now add the worker
                        AddWorker (worker, service);

                        Log (string.Format ("READY processed. Worker {0} added to service {1}",
                                            workerId,
                                            serviceName));
                    }
                    break;
                case MDPCommand.Reply:
                    if (workerIsKnown)
                    {
                        var worker = m_knownWorkers.Find (w => w.Id == workerId);
                        // remove the client return envelope and insert the protocol header 
                        // and service name then rewrap the envelope
                        var client = UnWrap (message);                  // [reply]
                        message.Push (worker.Service.Name);             // [service name][reply]
                        message.Push (MDPClientHeader);                 // [protocol header][service name][reply]
                        var reply = Wrap (client, message);             // [client adr][e][protocol header][service name][reply]

                        Socket.SendMessage (reply);

                        DebugLog (string.Format ("REPLY from {0} received and send to {1} -> {2}",
                                            workerId,
                                            client.ConvertToString (),
                                            message));
                        // relist worker for further requests
                        AddWorker (worker, worker.Service);
                    }
                    break;
                case MDPCommand.Heartbeat:
                    if (workerIsKnown)
                    {
                        var worker = m_knownWorkers.Find (w => w.Id == workerId);
                        worker.Expiry = DateTime.UtcNow + m_heartbeatExpiry;

                        DebugLog (string.Format ("HEARTBEAT from {0} received.", workerId));
                    }
                    break;
                default:
                    Log ("ERROR: Invalid MDPCommand received or message received!");
                    break;
            }
        }
Example #8
0
        /// <summary>
        ///     sends a message to a specific worker with a specific command
        ///     and add an option option
        /// </summary>
        private void WorkerSend (Worker worker, MDPCommand command, NetMQMessage message, string option = null)
        {
            var msg = message ?? new NetMQMessage ();

            // stack protocol envelope to start of message
            if (!ReferenceEquals (option, null))
                msg.Push (option);

            msg.Push (new[] { (byte) command });
            msg.Push (MDPConstants.MDP_WORKER_HEADER);
            // stack routing envelope
            var request = Wrap (worker.Identity, msg);

            DebugLog ($"Sending {request}");
            // send to worker
            Socket.SendMultipartMessage (request);
        }
Example #9
0
 private bool IsWaiting(Worker worker)
 {
     return(m_waitingWorkers.Contains(worker));
 }
Example #10
0
 private bool IsWaiting(Worker worker)
 {
     return m_waitingWorkers.Contains (worker);
 }
Example #11
0
        public void Equals_DifferentTypes_ShouldReturnFalse()
        {
            var service = new Service("service");
            var other = new Worker("id", new NetMQFrame("id"), service);

            Assert.That(service.Equals(other), Is.False);
        }
Example #12
0
        public void DeleteWorker_AllWorker_ShouldEmptyWaitingAndKnown()
        {
            var service = new Service("service");

            for (var i = 0; i < 10; i++)
            {
                var id = $"W0{i:N3}";
                var worker = new Worker(id, new NetMQFrame(id), service);
                service.AddWaitingWorker(worker);
                service.DeleteWorker(worker);
            }

            Assert.That(service.WaitingWorkers, Is.Empty);
            Assert.That(service.DoWorkersExist(), Is.False);
        }
Example #13
0
        public void GetNextWorker_GetAllWaitingWorkers_ShouldReturnEmptyWaitingAndLeaveKnownUnchanged()
        {
            var service = new Service("service");

            for (var i = 0; i < 10; i++)
            {
                var id = $"W0{i:N3}";
                var worker = new Worker(id, new NetMQFrame(id), service);
                service.AddWaitingWorker(worker);
                service.GetNextWorker();
            }

            Assert.That(service.WaitingWorkers, Is.Empty);
            Assert.That(service.DoWorkersExist(), Is.True);
        }
Example #14
0
        /// <summary>
        ///     process a READY, REPLY, HEARTBEAT, DISCONNECT message sent to the broker by a worker
        /// </summary>
        /// <param name="sender">the sender identity frame</param>
        /// <param name="message">the message sent</param>
        public void ProcessWorkerMessage ([NotNull] NetMQFrame sender, [NotNull] NetMQMessage message)
        {
            // should be
            // READY        [mdp command][service name]
            // REPLY        [mdp command][client adr][e][reply]
            // HEARTBEAT    [mdp command]
            if (message.FrameCount < 1)
                throw new ApplicationException ("Message with too few frames received.");

            var mdpCommand = message.Pop ();                // get the mdp command frame it should have only one byte payload

            if (mdpCommand.BufferSize > 1)
                throw new ApplicationException ("The MDPCommand frame had more than one byte!");

            var cmd = (MDPCommand) mdpCommand.Buffer[0];    // [service name] or [client adr][e][reply]
            var workerId = sender.ConvertToString ();       // get the id of the worker sending the message
            var workerIsKnown = m_knownWorkers.Any (w => w.Id == workerId);

            switch (cmd)
            {
                case MDPCommand.Ready:
                    if (workerIsKnown)
                    {
                        // then it is not the first command in session -> WRONG
                        // if the worker is know to a service, remove it from that
                        // service and a potential waiting list therein
                        RemoveWorker (m_knownWorkers.Find (w => w.Id == workerId));

                        Log ($"READY out of sync. Removed worker {workerId}.");
                    }
                    else
                    {
                        // now a new - not know - worker sent his READY initiation message
                        // attach worker to service and mark as idle - worker has send READY as first message
                        var serviceName = message.Pop ().ConvertToString ();
                        var service = ServiceRequired (serviceName);
                        // create a new worker and set the service it belongs to
                        var worker = new Worker (workerId, sender, service);
                        // now add the worker
                        AddWorker (worker, service);

                        Log ($"READY processed. Worker {workerId} added to service {serviceName}");
                    }
                    break;
                case MDPCommand.Reply:
                    if (workerIsKnown)
                    {
                        var worker = m_knownWorkers.Find (w => w.Id == workerId);
                        // remove the client return envelope and insert the protocol header
                        // and service name then rewrap the envelope
                        var client = UnWrap (message);                  // [reply]
                        message.Push (worker.Service.Name);             // [service name][reply]
                        message.Push (MDPConstants.MDP_CLIENT_HEADER);  // [protocol header][service name][reply]
                        var reply = Wrap (client, message);             // [client adr][e][protocol header][service name][reply]

                        Socket.SendMultipartMessage (reply);

                        DebugLog ($"REPLY from {workerId} received and send to {client.ConvertToString()} -> {message}");
                        // relist worker for further requests
                        AddWorker (worker, worker.Service);
                    }
                    break;
                case MDPCommand.Heartbeat:
                    if (workerIsKnown)
                    {
                        var worker = m_knownWorkers.Find (w => w.Id == workerId);
                        worker.Expiry = DateTime.UtcNow + m_heartbeatExpiry;

                        DebugLog ($"HEARTBEAT from {workerId} received.");
                    }
                    break;
                default:
                    Log ("ERROR: Invalid MDPCommand received or message received!");
                    break;
            }
        }
Example #15
0
        /// <summary>
        /// Deletes worker from the list of known workers and
        /// if the worker is registered for waiting removes it 
        /// from that list as well
        /// in order to synchronize the deleting access to the 
        /// local lists <c>m_syncRoot</c> is used to lock
        /// </summary>
        /// <param name="worker">the worker to delete</param>
        public void DeleteWorker(Worker worker)
        {
            if (IsKnown (worker.Id))
                m_workers.Remove (worker);

            if (IsWaiting (worker))
                m_waitingWorkers.Remove (worker);
        }
Example #16
0
 private bool IsKnown(Worker worker)
 {
     return m_workers.Contains (worker);
 }
Example #17
0
        public void GetNextWorker_SomeWaitingWorker_ShouldReturnOldestWorkerFirst()
        {
            Worker oldestWorker = null;
            var service = new Service("service");

            for (var i = 0; i < 10; i++)
            {
                var id = $"W0{i:N3}";
                var worker = new Worker(id, new NetMQFrame(id), service);

                if (i == 0)
                    oldestWorker = worker;

                service.AddWaitingWorker(worker);
            }

            Assert.That(service.GetNextWorker(), Is.EqualTo(oldestWorker));
            Assert.That(service.WaitingWorkers.Count(), Is.EqualTo(9));
        }
Example #18
0
        /// <summary>
        ///     removes the worker from the known worker list and
        ///     from the service it refers to if it exists and
        ///     potentially from the waiting list therein
        /// </summary>
        /// <param name="worker"></param>
        private void RemoveWorker (Worker worker)
        {
            if (m_services.Contains (worker.Service))
            {
                var service = m_services.Find (s => s.Equals (worker.Service));
                service.DeleteWorker (worker);

                DebugLog ($"removed worker {worker.Id} from service {service.Name}");
            }

            m_knownWorkers.Remove (worker);

            DebugLog ($"removed {worker.Id} from known worker.");
        }
Example #19
0
 private bool IsKnown(Worker worker)
 {
     return(m_workers.Contains(worker));
 }