private async Task <bool> SendPulsesOrHeartbeatToWebSocket(Task <WebSocketReceiveResult> receive, WebSocket webSocket, LiveReplicationPulsesCollector collector, MemoryStream ms, int timeToWait) { if (receive.IsCompleted || webSocket.State != WebSocketState.Open) { return(false); } var tuple = await collector.Pulses.TryDequeueAsync(TimeSpan.FromMilliseconds(timeToWait)); if (tuple.Item1 == false) { await webSocket.SendAsync(WebSocketHelper.Heartbeat, WebSocketMessageType.Text, true, Database.DatabaseShutdown); return(true); } ms.SetLength(0); using (ContextPool.AllocateOperationContext(out JsonOperationContext context)) using (var writer = new BlittableJsonTextWriter(context, ms)) { var pulse = tuple.Item2; context.Write(writer, pulse.ToJson()); } ms.TryGetBuffer(out ArraySegment <byte> bytes); await webSocket.SendAsync(bytes, WebSocketMessageType.Text, true, Database.DatabaseShutdown); return(true); }
public async Task EnsureNoReplicationLoop(RavenServer server, string database) { var storage = await server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(database); using (var collector = new LiveReplicationPulsesCollector(storage)) { var etag1 = storage.DocumentsStorage.GenerateNextEtag(); await Task.Delay(3000); var etag2 = storage.DocumentsStorage.GenerateNextEtag(); Assert.True(etag1 + 1 == etag2, "Replication loop found :("); var groups = collector.Pulses.GetAll().GroupBy(p => p.Direction); foreach (var group in groups) { var key = group.Key; var count = group.Count(); Assert.True(count < 50, $"{key} seems to be excessive ({count})"); } } }
public async Task PulsesLive() { using (var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync()) { var receiveBuffer = new ArraySegment <byte>(new byte[1024]); var receive = webSocket.ReceiveAsync(receiveBuffer, Database.DatabaseShutdown); using (var ms = new MemoryStream()) using (var collector = new LiveReplicationPulsesCollector(Database)) { // 1. Send data to webSocket without making UI wait upon opening webSocket await SendPulsesOrHeartbeatToWebSocket(receive, webSocket, collector, ms, 100); // 2. Send data to webSocket when available while (Database.DatabaseShutdown.IsCancellationRequested == false) { if (await SendPulsesOrHeartbeatToWebSocket(receive, webSocket, collector, ms, 4000) == false) { break; } } } } }