Example #1
0
        private void QueueCompleted(Task result, T queue)
        {
            if (queue.ReQueue)
            {
                lock (_Queues) _Queues.Add(queue);
            }
            if (queue.ReQueueAfterRunComplete)
            {
                lock (_ReQueues) _ReQueues.Add(queue);
            }
            if (result.IsFaulted)
            {
                OnTaskException?.Invoke(result.Exception, queue);
            }
            OnQueueComplete?.Invoke(result, queue);
            if (!queue.ReQueue && !queue.ReQueueAfterRunComplete)
            {
                queue.Dispose();
            }

            lock (_Runnings) _Runnings.Remove(queue);
            if (RunAsParty)
            {
                if (RunningCount == 0 && MaxRun > 0)
                {
                    OnQueueNextGroup?.Invoke();
                    RunNewQueue();
                }
            }
            else
            {
                RunNewQueue();
            }
        }
Example #2
0
        private void ScheduledTask_OnException(ScheduledTask task, Exception exception)
        {
            string message = $"An error occurred while executing {task.Name}";

            WorkerLogger.Error(message, exception);
            Store($"{message}, Exception = {exception.Message}");

            OnTaskException?.Invoke(this, new TaskExceptionEventArgs(task, exception));
        }
Example #3
0
        protected virtual void NotifyException()
        {
            if (State == TaskState.Error)
            {
                if (OnTaskException != null)
                {
                    OnTaskException.Invoke(this);
                }

                ExceptionWasNotified = true;
            }
        }
        /// <summary>
        /// Initialize the connection and set up the handshake
        /// Topics: (https://dev.twitch.tv/docs/pubsub#topics)
        /// </summary>
        /// <param name="host">Host server to connect to</param>
        /// <param name="accessToken">Access token with the required scopes to listen for the desired topics</param>
        /// <param name="topics">Topics to handle</param>
        /// <returns></returns>
        public static async Task Start(string host, string accessToken, string[] topics)
        {
            try
            {
                InitComponents();

                await ConnectAsync(host);

                _ = Task.Run(() => ProcessMessageQueue());
                _ = Task.Run(() => Monitor());

                await Heartbeat();
                await Listen(accessToken, topics);
            }
            catch (Exception ex)
            {
                OnTaskException?.Invoke(new TaskExceptionArgs(ex, "Startup Failed"));
                throw ex;
            }
        }
        /// <summary>
        /// Handle incoming websocket messages that are added to the message queue
        /// </summary>
        public static void ProcessMessageQueue()
        {
            CancellationToken cancellationToken = s_ProcessCancellationSource.Token;

            while (!cancellationToken.IsCancellationRequested)
            {
                if (s_MessageQueue.Count == 0)
                {
                    Thread.Sleep(1);
                    continue;
                }

                if (s_MessageQueue.TryTake(out string item))
                {
                    Payload response = JsonConvert.DeserializeObject <Payload>(item);
                    OnPayload?.Invoke(response);

                    switch (response.type)
                    {
                    case "PONG":
                    {
                        s_PongReceived = true;
                        Task.Run(() => DelayedHeartbeat());
                    }
                    break;

                    case "RECONNECT":
                    {
                        OnServerRestart?.Invoke();
                    }
                    break;

                    case "RESPONSE":
                    {
                        PayloadResponse payloadResponse = JsonConvert.DeserializeObject <PayloadResponse>(item);
                        if (payloadResponse.nonce != s_ListenNonce)
                        {
                            throw new AccessViolationException($"The nonce received does not match {s_ListenNonce} Unknown: {payloadResponse.nonce}");
                        }
                        OnResponse?.Invoke(payloadResponse);
                    }
                    break;

                    case "MESSAGE":
                    {
                        PayloadMessage payloadMessage = JsonConvert.DeserializeObject <PayloadMessage>(item);

                        string topicKey = GetTopicKey(payloadMessage.data.topic);

                        if (topicKey == "whispers")
                        {
                            JObject jobj = JObject.Parse(payloadMessage.data.message);

                            JToken jtokenType       = jobj.GetValue("type");
                            JToken jtokenData       = jobj.GetValue("data");
                            JToken jtokenDataObject = jobj.GetValue("data_object");
                            string type             = jtokenType.ToString();

                            try
                            {
#pragma warning disable 0618
                                Whispers.Data data        = JsonConvert.DeserializeObject <Whispers.Data>(jtokenData.ToString());
                                Whispers.Data data_object = JsonConvert.DeserializeObject <Whispers.Data>(jtokenDataObject.ToString());
#pragma warning restore 0618
                                payloadMessage.data.message = JObject.FromObject(new { type, data, data_object }).ToString().Replace("\n", "").Replace("\r", "");

                                if (s_TopicEvents.TryGetValue(topicKey, out Action <IPayload> value))
                                {
                                    value?.Invoke(payloadMessage);
                                }
                            }
                            catch (Exception ex)
                            {
                                OnTaskException?.Invoke(new TaskExceptionArgs(ex, "ProcessMessageQueue Whisper"));
                            }
                        }
                        else
                        {
                            if (s_TopicEvents.TryGetValue(topicKey, out Action <IPayload> value))
                            {
                                value?.Invoke(payloadMessage);
                            }
                        }
                    }
                    break;

                    default:
                        break;
                    }
                }
            }
            _ = InvokeReconnectWithBackoff(ReconnectReason.DefaultBreak);
        }
        /// <summary>
        /// Monitor incoming websocket messages and adds them to a message queue
        /// </summary>
        /// <returns></returns>
        public static async Task Monitor()
        {
            CancellationToken cancellationToken = s_CancellationSource.Token;

            while (cancellationToken.IsCancellationRequested == false)
            {
                try
                {
                    if ((s_WebSocket.State == WebSocketState.Open ||
                         s_WebSocket.State == WebSocketState.CloseSent) && cancellationToken.IsCancellationRequested == false)
                    {
                        ArraySegment <byte>    buffer = new ArraySegment <byte>(new byte[1024]);
                        WebSocketReceiveResult result = await s_WebSocket.ReceiveAsync(buffer, cancellationToken);

                        if (result == null)
                        {
                            continue;
                        }

                        if (result.MessageType != WebSocketMessageType.Text)
                        {
                            Thread.Sleep(1);
                            continue;
                        }

                        if (result.EndOfMessage == false)
                        {
                            s_Message += Encoding.UTF8.GetString(buffer.Array, 0, result.Count);
                        }
                        else
                        {
                            s_Message += Encoding.UTF8.GetString(buffer.Array, 0, result.Count);
                            s_MessageQueue.Add(s_Message);
                            s_Message = string.Empty;
                        }
                    }
                    else if (s_WebSocket.State == WebSocketState.Closed)
                    {
                        await InvokeReconnectWithBackoff(ReconnectReason.Closed);

                        break;
                    }
                    else if (s_WebSocket.State == WebSocketState.Aborted)
                    {
                        await InvokeReconnectWithBackoff(ReconnectReason.Aborted);

                        break;
                    }
                }
                catch (OperationCanceledException ex)
                {
                    OnTaskException?.Invoke(new TaskExceptionArgs(ex, "OperationCanceledException"));
                }
                catch (WebSocketException ex)
                {
                    OnTaskException?.Invoke(new TaskExceptionArgs(ex, "WebSocketException"));
                }
                catch (Exception ex)
                {
                    OnTaskException?.Invoke(new TaskExceptionArgs(ex, "Monitor"));
                    await InvokeReconnectWithBackoff(ReconnectReason.Exception);

                    break;
                }
            }
            await InvokeReconnectWithBackoff(ReconnectReason.OperationCanceled);
        }