// .split try to call a service // Here, we first check if the requested MDP service is defined or not, // using a MMI lookup to the Majordomo broker. If the service exists, // we send a request and wait for a reply using the conventional MDP // client API. This is not meant to be fast, just very simple: static bool Titanic_ServiceSuccess(Guid uuid, CancellationTokenSource cts) { // Load request message, service will be first frame string fn = TitanicCommon.RequestFilename(uuid); FileStream fs; if (!fn.TryFileOpenRead(out fs)) { // If the client already close request, treat as successful return(true); } fs.Dispose(); ZMessage request = fn.DeserializeFromXml <ZMessage>(); var service = request.Pop(); string servicename = service.ToString(); bool res = false; // Create MDP client session with short timeout using (var client = new MajordomoClient("tcp://127.0.0.1:5555", false)) { client.Set_Timeout(1000); // 1sec client.Set_Retries(1); // only 1 retry // Use MMI protocol to check if service is available ZMessage mmirequest = new ZMessage { service }; bool service_ok; using (var mmireply = client.Send("mmi.service", mmirequest, cts)) service_ok = (mmireply != null && mmireply.First().ToString().Equals("200")); res = false; if (service_ok) { using (ZMessage reply = client.Send(servicename, request, cts)) if (reply != null) { fn = TitanicCommon.ReplyFilename(uuid); reply.SerializeToXml(fn); res = true; } else { request.Dispose(); } } } return(res); }
// .split Titanic request service // The {{titanic.request}} task waits for requests to this service. It writes // each request to disk and returns a UUID to the client. The client picks // up the reply asynchronously using the {{titanic.reply}} service: private static void Titanic_Request(ZContext ctx, ZSocket backendpipe, CancellationTokenSource cancellor, object[] args) { using (MajordomoWorker worker = new MajordomoWorker("tcp://127.0.0.1:5555", "titanic.request", (bool)args[0])) { ZMessage reply = null; while (true) { // Send reply if it's not null // And then get next request from broker ZMessage request = worker.Recv(reply, cancellor); if (request == null) { break; // Interrupted, exit } // Ensure message directory exists Directory.CreateDirectory(TitanicCommon.TITANIC_DIR); // Generate UUID and save mesage to disk Guid uuid = TitanicCommon.GenerateUuid(); string fn = TitanicCommon.RequestFilename(uuid); request.SerializeToXml(fn); request.Dispose(); // Send UUID through tho message queue reply = new ZMessage(); reply.Add(new ZFrame(uuid.ToString())); ZError error; if (!backendpipe.Send(reply, out error)) { if (error.Equals(ZError.ETERM)) { break; } } //backendpipe.Send(reply); // Now send UUID back to client // Done by the mdwrk_recv() at the top of the loop reply = new ZMessage(); reply.Add(new ZFrame("200")); reply.Add(new ZFrame(uuid.ToString())); } } }
// .split Titanic close task // The {{titanic.close}} task removes any waiting replies for the request // (specified by UUID). It's idempotent, so it is safe to call more than // once in a row: private static void Titanic_Close(ZContext context, CancellationTokenSource cts, bool verbose) { using (var worker = new MajordomoWorker("tcp://127.0.0.1:5555", "titanic.close", verbose)) { ZMessage reply = null; while (true) { ZMessage request = worker.Recv(reply, cts); if (request == null) { break; } var g = Guid.Parse(request.Pop().ReadString()); var reqfn = TitanicCommon.RequestFilename(g); var repfn = TitanicCommon.ReplyFilename(g); File.Delete(reqfn); File.Delete(repfn); request.Dispose(); reply = new ZMessage(); reply.Add(new ZFrame("200")); } } }
// .split Titanic reply service // The {{titanic.reply}} task checks if there's a reply for the specified // request (by UUID), and returns a 200 (OK), 300 (Pending), or 400 // (Unknown) accordingly: private static void Titanic_Reply(ZContext context, CancellationTokenSource cts, bool verbose) { using (var worker = new MajordomoWorker("tcp://127.0.0.1:5555", "titanic.reply", verbose)) { ZMessage reply = null; while (true) { var request = worker.Recv(reply, cts); if (request == null) { break; // Interrupted, exit } var g = Guid.Parse(request.Pop().ReadString()); var reqfn = TitanicCommon.RequestFilename(g); var repfn = TitanicCommon.ReplyFilename(g); if (File.Exists(repfn)) { reply = repfn.DeserializeFromXml <ZMessage>(); reply.Prepend(new ZFrame("200")); } else { reply = new ZMessage(); if (File.Exists(reqfn)) { reply.Prepend(new ZFrame("300")); //Pending } else { reply.Prepend(new ZFrame("400")); //Unknown } } request.Dispose(); } } }