public override async Task SyncService(BuildStatusToken statusToken) { try { isSyncing = true; connection.IsSynced = false; connection.Service = Service; Task publishTask = Task.Run(() => SendMessagesHandler(connection)); Task pingTask = Task.Run(() => SendPingsHandler(connection)); Task receiveTask = Task.Run(() => ReceiveHandler(connection)); Task processTask = Task.Run(() => ProcessHandler(connection)); await connection.SendCommand(SyncCmd, false, TimeSpan.FromSeconds(1000), statusToken.EndTask); connection.IsSynced = true; connection.Task = Task.WhenAll(publishTask, pingTask, receiveTask, processTask); } catch (Exception e) { try { await connection.CloseAsync(e, true); } catch { } throw; } finally { isSyncing = false; } }
private async Task ProcessHandler(OwnTcpClientConnection connection) { while (true) { (_, OwnTcpMessage item) = await connection.ProcessQueue.Dequeue().ConfigureAwait(false); if (connection.ProcessQueue.IsEnd) { break; } try { LockTopic(item.Topic, item.Payload); bool handleAction() => HandlerMessage(item); bool success = helper == null? handleAction() : await helper.InvokeDispatcher(handleAction); if (success) { continue; } Exception e = new Exception($"Handle Message not successful. Topic: {item.Topic}"); await connection.CloseAsync(e, false); } catch (Exception e) { e = new Exception($"Handle Message error. Topic: {item.Topic}", e); await connection.CloseAsync(e, false); break; } finally { UnlockTopic(item.Topic); } } }
private static async Task SendMessagesHandler(OwnTcpClientConnection connection) { try { uint count = 0; while (!connection.SendQueue.IsEnded) { OwnTcpSendMessage send = connection.SendQueue.Dequeue(); if (connection.SendQueue.IsEnded) { break; } send.Message.ID = count++; if (!send.Message.IsFireAndForget) { connection.Waits.Add(send.Message.ID, send); } byte[] data = GetBytes(send.Message).ToArray(); await connection.Stream.WriteAsync(data, 0, data.Length); await connection.Stream.FlushAsync(); if (send.Message.IsFireAndForget) { send.SetResult(true); } if (send.Message.Topic == CloseCmd) { break; } } } catch (Exception e) { await connection.CloseAsync(new Exception("SendMessageHandler error", e), false); } }
private static async Task SendPingsHandler(OwnTcpClientConnection connection) { Task cancelTask = connection.PingSem.WaitAsync(); try { while (connection.Client?.Connected == true) { Task delayTask = Task.Delay(pingInterval); await Task.WhenAny(delayTask, cancelTask); if (cancelTask.IsCompleted) { return; } await connection.SendCommand(PingCmd, false, TimeSpan.FromSeconds(2), cancelTask); } } catch (Exception e) { await connection.CloseAsync(new Exception("ReceiveHandler error", e), false); } }
private async Task ReceiveHandler(OwnTcpClientConnection connection) { try { while (connection.Client?.Connected == true) { OwnTcpMessage message = await connection.ReadMessage(); if (message == null || connection.Client?.Connected != true) { break; } switch (message.Topic) { case AnwserCmd: int code = BitConverter.ToInt32(message.Payload, 0); if (code == 200) { connection.Waits[message.ID].SetResult(true); connection.Waits.Remove(message.ID); } else { await connection.CloseAsync(new Exception("Negative Answer"), false); } break; case CloseCmd: Exception e = new Exception("Server sent close"); await connection.CloseAsync(e, false); return; case SyncCmd: ByteQueue data = message.Payload; void syncAction() => data.DequeueService(connection.Service, Service.CreateSourcePlaylist, Service.CreatePlaylist); if (helper == null) { syncAction(); } else { await helper.InvokeDispatcher(syncAction); } connection.Waits[message.ID].SetResult(true); connection.Waits.Remove(message.ID); break; default: if (connection.IsSynced) { await connection.ProcessQueue.Enqueue(message); } break; } } } catch (Exception e) { await connection.CloseAsync(new Exception("ReceiveHandler error", e), false); } }