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); }
/// <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); } }
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)); }
/// <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); }
/// <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)); }
/// <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); }
/// <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; } }
/// <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); }
private bool IsWaiting(Worker worker) { return(m_waitingWorkers.Contains(worker)); }
private bool IsWaiting(Worker worker) { return m_waitingWorkers.Contains (worker); }
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); }
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); }
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); }
/// <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; } }
/// <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); }
private bool IsKnown(Worker worker) { return m_workers.Contains (worker); }
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)); }
/// <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."); }
private bool IsKnown(Worker worker) { return(m_workers.Contains(worker)); }