private void NotifySubscribers(string type, BlittableJsonReaderObject value, List <DatabaseConnectionState> states) { switch (type) { case nameof(DocumentChange): var documentChange = DocumentChange.FromJson(value); foreach (var state in states) { state.Send(documentChange); } break; case nameof(CounterChange): var counterChange = CounterChange.FromJson(value); foreach (var state in states) { state.Send(counterChange); } break; case nameof(IndexChange): var indexChange = IndexChange.FromJson(value); foreach (var state in states) { state.Send(indexChange); } break; case nameof(OperationStatusChange): var operationStatusChange = OperationStatusChange.FromJson(value, _conventions); foreach (var state in states) { state.Send(operationStatusChange); } break; case nameof(TopologyChange): var topologyChange = TopologyChange.FromJson(value); _requestExecutor?.UpdateTopologyAsync(new ServerNode { Url = topologyChange.Url, Database = topologyChange.Database }, 0, true, "topology-change-notification").ConfigureAwait(false); break; default: throw new NotSupportedException(type); } }
private async Task ProcessChanges() { using (_requestExecutor.ContextPool.AllocateOperationContext(out var context)) { while (_cts.IsCancellationRequested == false) { context.Reset(); context.Renew(); var state = new JsonParserState(); using (var stream = new WebSocketStream(_client, _cts.Token)) using (context.GetMemoryBuffer(out JsonOperationContext.MemoryBuffer buffer)) using (var parser = new UnmanagedJsonParser(context, state, "changes/receive")) using (var builder = new BlittableJsonDocumentBuilder(context, BlittableJsonDocumentBuilder.UsageMode.None, "readArray/singleResult", parser, state)) using (var peepingTomStream = new PeepingTomStream(stream, context)) { if (await UnmanagedJsonParserHelper.ReadAsync(peepingTomStream, parser, state, buffer).ConfigureAwait(false) == false) { continue; } if (state.CurrentTokenType != JsonParserToken.StartArray) { continue; } while (true) { builder.Reset(); builder.Renew("changes/receive", BlittableJsonDocumentBuilder.UsageMode.None); if (await UnmanagedJsonParserHelper.ReadAsync(peepingTomStream, parser, state, buffer).ConfigureAwait(false) == false) { continue; } if (state.CurrentTokenType == JsonParserToken.EndArray) { break; } await UnmanagedJsonParserHelper.ReadObjectAsync(builder, peepingTomStream, parser, buffer).ConfigureAwait(false); using (var json = builder.CreateReader()) { try { if (json.TryGet(nameof(TopologyChange), out bool supports) && supports) { GetOrAddConnectionState("Topology", "watch-topology-change", "", ""); await _requestExecutor.UpdateTopologyAsync(new RequestExecutor.UpdateTopologyParameters(_serverNode) { TimeoutInMs = 0, ForceUpdate = true, DebugTag = "watch-topology-change" }).ConfigureAwait(false); continue; } if (json.TryGet("Type", out string type) == false) { continue; } switch (type) { case "Error": json.TryGet("Exception", out string exceptionAsString); NotifyAboutError(new Exception(exceptionAsString)); break; case "Confirm": if (json.TryGet("CommandId", out int commandId) && _confirmations.TryRemove(commandId, out var tcs)) { tcs.TrySetResult(null); } break; default: json.TryGet("Value", out BlittableJsonReaderObject value); NotifySubscribers(type, value, _counters.ForceEnumerateInThreadSafeManner().Select(x => x.Value).ToList()); break; } } catch (Exception e) { NotifyAboutError(e); throw new ChangeProcessingException(e); } } } } } } }