public void Notify(string @event, object @internal, NotifyData data, byte[] payload) { _logger.LogDebug($"notify() [event:{@event}]"); if (_closed) { throw new InvalidStateException("PayloadChannel closed"); } var notification = new { @event, @internal, data }; var ns1Bytes = Netstring.Encode(notification.ToCamelCaseJson()); var ns2Bytes = Netstring.Encode(payload); if (ns1Bytes.Length > NsMessageMaxLen) { throw new Exception("PayloadChannel notification too big"); } if (ns2Bytes.Length > NsMessageMaxLen) { throw new Exception("PayloadChannel payload too big"); } Loop.Default.Sync(() => { try { // This may throw if closed or remote side ended. _producerSocket.Write(ns1Bytes, ex => { if (ex != null) { _logger.LogError(ex, "_producerSocket.Write() | error"); } }); } catch (Exception ex) { _logger.LogWarning($"notify() | sending notification failed: {ex}"); return; } try { // This may throw if closed or remote side ended. _producerSocket.Write(ns2Bytes, ex => { if (ex != null) { _logger.LogError(ex, "_producerSocket.Write() | error"); } }); } catch (Exception ex) { _logger.LogWarning($"notify() | sending notification failed: {ex}"); return; } }); }
public Task <string?> RequestAsync(MethodId methodId, object? @internal = null, object?data = null) { var method = methodId.GetEnumStringValue(); var id = _nextId < Int32.MaxValue ? ++_nextId : (_nextId = 1); // TODO: (alby)线程同步 _logger.LogDebug($"RequestAsync() | [method:{method}, id:{id}]"); if (_closed) { throw new InvalidStateException("Channel closed"); } var requestMesssge = new RequestMessage { Id = id, Method = method, Internal = @internal, Data = data, }; var ns = NetstringWriter.Encode(requestMesssge.ToCamelCaseJson()); var bytes = Encoding.UTF8.GetBytes(ns); if (bytes.Length > NsMessageMaxLen) { throw new Exception("Channel request too big"); } var tcs = new TaskCompletionSource <string?>(); var sent = new Sent { RequestMessage = requestMesssge, Close = () => { if (!_sents.Remove(id)) { return; } tcs.TrySetException(new InvalidStateException("Channel closed")); }, Resolve = data => { if (!_sents.Remove(id)) { return; } tcs.TrySetResult(data); }, Reject = e => { if (!_sents.Remove(id)) { return; } tcs.TrySetException(e); }, }; _sents.Add(id, sent); tcs.WithTimeout(TimeSpan.FromSeconds(15 + (0.1 * _sents.Count)), () => _sents.Remove(id)); Loop.Default.Sync(() => { try { // This may throw if closed or remote side ended. _producerSocket.Write(ns, ex => { if (ex != null) { _logger.LogError(ex, "_producerSocket.Write() | error"); tcs.TrySetException(ex); } }); } catch (Exception ex) { _logger.LogError(ex, "_producerSocket.Write() | error"); tcs.TrySetException(ex); } }); return(tcs.Task); }
public Task <string?> RequestAsync(MethodId methodId, object? @internal = null, object?data = null) { if (_closed) { throw new InvalidStateException("Channel closed"); } var method = methodId.GetEnumStringValue(); var id = InterlockedExtensions.Increment(ref _nextId); // NOTE: For testinng //_logger.LogDebug($"RequestAsync() | [Method:{method}, Id:{id}]"); var requestMesssge = new RequestMessage { Id = id, Method = method, Internal = @internal, Data = data, }; var nsBytes = Netstring.Encode(requestMesssge.ToCamelCaseJson()); if (nsBytes.Length > NsMessageMaxLen) { throw new Exception("Channel request too big"); } var tcs = new TaskCompletionSource <string?>(); var sent = new Sent { RequestMessage = requestMesssge, Resolve = data => { if (!_sents.TryRemove(id, out var _)) { tcs.TrySetException(new Exception($"Received response does not match any sent request [id:{id}]")); return; } tcs.TrySetResult(data); }, Reject = e => { if (!_sents.TryRemove(id, out var _)) { tcs.TrySetException(new Exception($"Received response does not match any sent request [id:{id}]")); return; } tcs.TrySetException(e); }, Close = () => { tcs.TrySetException(new InvalidStateException("Channel closed")); }, }; if (!_sents.TryAdd(id, sent)) { throw new Exception($"Error add sent request [id:{id}]"); } tcs.WithTimeout(TimeSpan.FromSeconds(15 + (0.1 * _sents.Count)), () => _sents.TryRemove(id, out var _)); Loop.Default.Sync(() => { try { // This may throw if closed or remote side ended. _producerSocket.Write(nsBytes, ex => { if (ex != null) { _logger.LogError(ex, "_producerSocket.Write() | Error"); sent.Reject(ex); } }); } catch (Exception ex) { _logger.LogError(ex, "_producerSocket.Write() | Error"); sent.Reject(ex); } }); return(tcs.Task); }