1 module nats.interface_; 2 3 public import core.time: Duration, seconds; 4 5 struct Msg 6 { 7 const(char)[] subject; 8 const(char)[] replySubject; 9 uint sid; 10 uint length; 11 Subscription subs; 12 const(ubyte)[] payload; 13 NatsResponse type; 14 15 scope string payloadAsString() @trusted 16 { 17 import std.string: assumeUTF; 18 import std.exception: assumeUnique; 19 20 return payload.assumeUTF.assumeUnique; 21 } 22 } 23 24 /* 25 NatsHandlers run in the eventloop thread and block the listener task while they process 26 (the message stream is ordered). This leads to two constraints: 27 1. Msg is scope parameter to avoid unnecessary copying/allocation 28 2. Delegate must be nothrow to avoid killing the listener task with unhandled exception 29 30 If you need to do more processing, it is better to copy the information you need from the 31 Msg struct and send to a task or worker task (ie in a different thread) 32 */ 33 alias NatsHandler = void delegate(scope Msg) @safe nothrow; 34 35 class Subscription 36 { 37 string subject; 38 string queueGroup; 39 ulong msgsReceived; 40 ulong msgsToExpire = ulong.max; 41 ulong bytesReceived; 42 NatsHandler handler; 43 uint sid; 44 bool closed; 45 } 46 47 class NatsProtocolException : Exception { 48 this(string message, string file = __FILE__, size_t line = __LINE__, Exception next = null) @safe 49 { 50 super(message, file, line, next); 51 } 52 } 53 54 struct NatsClientConfig 55 { 56 string natsUri; 57 string clientId; 58 Duration heartbeatInterval = 5.seconds; 59 Duration reconnectInterval = 15.seconds; 60 Duration connectTimeout = 15.seconds; 61 } 62 63 enum NatsState : byte { INIT, CONNECTING, CONNECTED, DISCONNECTED, RECONNECTING, CLOSED } 64 65 enum NatsResponse : byte { FRAGMENT, MSG, MSG_REPLY, PING, PONG, INFO, OK, ERR }