/// <summary> /// Common entry-point for all the "request" public synchronous methods /// </summary> /// <param name="message"></param> /// <param name="timeout"></param> /// <param name="token"></param> /// <returns></returns> private MsgOut RequestCore( MsgIn message, TimeSpan timeout, CancellationToken token ) { InFlightRequest request = null; try { request = this._rrmgr.SetupRequest(message); this.PublishCore(message, timeout, token); } catch (Exception ex) { if (request != null) { this._rrmgr.DropRequest(request); request.Dispose(); } throw ex; } return(request.GetReply(timeout, token)); }
/// <summary> /// Publishes a <see cref="MsgIn"/> instance, which includes the subject, an optional reply, and an /// optional data field. /// </summary> /// <remarks> /// <para>NATS implements a publish-subscribe message distribution model. NATS publish subscribe is a /// one-to-many communication. A publisher sends a message on a subject. Any active subscriber listening /// on that subject receives the message. Subscribers can register interest in wildcard subjects.</para> /// <para>In the basic NATS platfrom, if a subscriber is not listening on the subject (no subject match), /// or is not acive when the message is sent, the message is not received. NATS is a fire-and-forget /// messaging system. If you need higher levels of service, you can either use NATS Streaming, or build the /// additional reliability into your client(s) yourself.</para> /// </remarks> /// <param name="message">A <see cref="MsgIn"/> instance containing the subject, optional reply, and data to publish /// to the NATS server.</param> /// <param name="timeout">Represents the time to wait for the connection going stable.</param> /// <param name="token">Propagates notification that operations should be canceled.</param> public void Publish(MsgIn message, TimeSpan timeout, CancellationToken token) { if (timeout <= TimeSpan.Zero) { throw new ArgumentException("Timeout must be greater than zero.", nameof(timeout)); } this.PublishCore(message, timeout, token); }
/// <summary> /// Sends a request payload and returns the response <see cref="MsgOut"/>, or throws /// <see cref="NATSTimeoutException"/> if the <paramref name="timeout"/> expires. /// </summary> /// <remarks> /// <para>NATS supports two flavors of request-reply messaging: point-to-point or one-to-many. Point-to-point /// involves the fastest or first to respond. In a one-to-many exchange, you set a limit on the number of /// responses the requestor may receive and instead must use a subscription (<see cref="ISubscription.AutoUnsubscribe(int)"/>). /// In a request-response exchange, publish request operation publishes a message with a reply subject expecting /// a response on that reply subject.</para> /// <para><see cref="Request(MsgIn, TimeSpan, CancellationToken)"/> will create an unique inbox for this request, sharing a single /// subscription for all replies to this <see cref="Connection"/> instance. However, if /// <see cref="ClientOptions.UseOldRequestStyle"/> is set, each request will have its own underlying subscription. /// The old behavior is not recommended as it may cause unnecessary overhead on connected NATS servers.</para> /// </remarks> /// <param name="message">A <see cref="MsgIn"/> instance containing the subject, optional reply, and data to publish /// to the NATS server.</param> /// <param name="timeout">Represents the overall time to wait for the connection going stable, if not, and for the message loopback.</param> /// <param name="token">Propagates notification that operations should be canceled.</param> /// <returns>A <see cref="MsgOut"/> with the response from the NATS server.</returns> public MsgOut Request(MsgIn message, TimeSpan timeout, CancellationToken token) { if (timeout <= TimeSpan.Zero) { throw new ArgumentException("Timeout must be greater than zero.", nameof(timeout)); } return(this.RequestCore(message, timeout, token)); }
/// <summary> /// Sets an <see cref="InFlightRequest"/> instance up, /// as proxy for a request-reply process. /// </summary> /// <param name="message"></param> /// <returns></returns> internal InFlightRequest SetupRequest(MsgIn message) { InFlightRequest request; lock (this._reqlocker) { request = new InFlightRequest(this, ++this._reqId); this._requestRegister.Add(request.ReqId, request); } message.InboxRequest = request; return(request); }
/// <summary> /// Common entry-point for all the "publish" public methods /// </summary> /// <param name="message"></param> /// <param name="timeout"></param> /// <param name="token"></param> private void PublishCore( MsgIn message, TimeSpan timeout, CancellationToken token ) { if (this._connmgr.IsLogicalStarted == false) { this._connmgr.WaitLogicalStart(timeout, token); } // Proactively reject payloads over the threshold set by server. int payloadLength = message.PayloadInternal.Length; if (payloadLength > this._connmgr.MaxPayload) { throw new NATSMaxPayloadException(); } //ensures the following section mutex-accessed lock (this._pubLocker) { //build the header as described here: //https://nats.io/documentation/internals/nats-protocol/ this._pubBuilder.Length = 0; this._pubBuilder.Append(InternalConstants._PUB_P_); this._pubBuilder.Append(message.Subject); this._pubBuilder.Append(' '); if (message.InboxRequest != null) { this._pubBuilder.Append(message.InboxRequest.ReplyToSubject); this._pubBuilder.Append(' '); } else if (message.ReplyTo.Length != 0) { this._pubBuilder.Append(message.ReplyTo); this._pubBuilder.Append(' '); } this._pubBuilder.Append(payloadLength.ToString(CultureInfo.InvariantCulture)); this._pubBuilder.Append(InternalConstants._CRLF_); int buflen = Encoding.UTF8.GetBytes(this._pubBuilder.ToString(), 0, this._pubBuilder.Length, this._pubProtoBuf, 0); //outstreams the pub data (header and payload) this._connmgr.WritePubData( new ArraySegment <byte>(this._pubProtoBuf, 0, buflen), message.PayloadInternal ); } }
/// <summary> /// Publishes a <see cref="MsgIn"/> instance, which includes the subject, an optional reply, and an /// optional data field. /// </summary> /// <remarks> /// <para>NATS implements a publish-subscribe message distribution model. NATS publish subscribe is a /// one-to-many communication. A publisher sends a message on a subject. Any active subscriber listening /// on that subject receives the message. Subscribers can register interest in wildcard subjects.</para> /// <para>In the basic NATS platfrom, if a subscriber is not listening on the subject (no subject match), /// or is not acive when the message is sent, the message is not received. NATS is a fire-and-forget /// messaging system. If you need higher levels of service, you can either use NATS Streaming, or build the /// additional reliability into your client(s) yourself.</para> /// </remarks> /// <param name="message">A <see cref="MsgIn"/> instance containing the subject, optional reply, and data to publish /// to the NATS server.</param> /// <param name="token">Propagates notification that operations should be canceled.</param> public void Publish(MsgIn message, CancellationToken token) { this.PublishCore(message, Timeout.InfiniteTimeSpan, token); }
/// <summary> /// Sends a request payload and returns the response <see cref="MsgOut"/>, or throws /// <see cref="NATSTimeoutException"/> if the <paramref name="timeout"/> expires. /// </summary> /// <remarks> /// <para>NATS supports two flavors of request-reply messaging: point-to-point or one-to-many. Point-to-point /// involves the fastest or first to respond. In a one-to-many exchange, you set a limit on the number of /// responses the requestor may receive and instead must use a subscription (<see cref="ISubscription.AutoUnsubscribe(int)"/>). /// In a request-response exchange, publish request operation publishes a message with a reply subject expecting /// a response on that reply subject.</para> /// <para><see cref="Request(MsgIn, CancellationToken)"/> will create an unique inbox for this request, sharing a single /// subscription for all replies to this <see cref="Connection"/> instance. However, if /// <see cref="ClientOptions.UseOldRequestStyle"/> is set, each request will have its own underlying subscription. /// The old behavior is not recommended as it may cause unnecessary overhead on connected NATS servers.</para> /// </remarks> /// <param name="message">A <see cref="MsgIn"/> instance containing the subject, optional reply, and data to publish /// to the NATS server.</param> /// <param name="token">Propagates notification that operations should be canceled.</param> /// <returns>A <see cref="MsgOut"/> with the response from the NATS server.</returns> public MsgOut Request(MsgIn message, CancellationToken token) { return(this.RequestCore(message, Timeout.InfiniteTimeSpan, token)); }
/// <summary> /// Sends a request payload and returns the response <see cref="MsgOut"/>, or throws /// <see cref="NATSTimeoutException"/> if the <paramref name="timeout"/> expires. /// </summary> /// <remarks> /// <para>NATS supports two flavors of request-reply messaging: point-to-point or one-to-many. Point-to-point /// involves the fastest or first to respond. In a one-to-many exchange, you set a limit on the number of /// responses the requestor may receive and instead must use a subscription (<see cref="ISubscription.AutoUnsubscribe(int)"/>). /// In a request-response exchange, publish request operation publishes a message with a reply subject expecting /// a response on that reply subject.</para> /// <para><see cref="RequestAsync(MsgIn, CancellationToken)"/> will create an unique inbox for this request, sharing a single /// subscription for all replies to this <see cref="Connection"/> instance. However, if /// <see cref="ClientOptions.UseOldRequestStyle"/> is set, each request will have its own underlying subscription. /// The old behavior is not recommended as it may cause unnecessary overhead on connected NATS servers.</para> /// </remarks> /// <param name="message">A <see cref="MsgIn"/> instance containing the subject, optional reply, and data to publish /// to the NATS server.</param> /// <param name="token">Propagates notification that operations should be canceled.</param> /// <returns>A task that represents the asynchronous read operation. The value of the <see cref="Task{TResult}.Result"/> /// parameter contains a <see cref="MsgOut"/> with the response from the NATS server.</returns> public Task <MsgOut> RequestAsync(MsgIn message, CancellationToken token) { return(this.RequestAsync(message, Timeout.InfiniteTimeSpan, token)); }