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 }