ShoutLib.Shouter.ShoutOrThrow C# (CSharp) Method

ShoutOrThrow() public method

Waits for a shout request message to arrive in the Pub/Sub subscription. Converts the text to uppercase and posts the results back to the website.
public ShoutOrThrow ( System cancellationToken ) : int
cancellationToken System
return int
        public int ShoutOrThrow(System.Threading.CancellationToken cancellationToken)
        {
            // Pull a shout request message from the subscription.
            string subscriptionPath = MakeSubscriptionPath(_init.SubscriptionName);
            WriteLog("Pulling shout request messages from " + subscriptionPath + "...",
                TraceEventType.Verbose);
            var pullRequest = _init.PubsubService.Projects.Subscriptions.Pull(
                new PullRequest()
                {
                    MaxMessages = 1,
                    ReturnImmediately = false
                }, subscriptionPath).ExecuteAsync();
            Task.WaitAny(new Task[] { pullRequest }, cancellationToken);
            var pullResponse = pullRequest.Result;

            int messageCount = pullResponse.ReceivedMessages == null ? 0
                : pullResponse.ReceivedMessages.Count;
            WriteLog("Received " + messageCount + " messages.",
                     TraceEventType.Information);
            if (messageCount < 1)
                return 0;  // Nothing pulled.  Nothing to do.

            // Examine the received message.
            var shoutRequestMessage = pullResponse.ReceivedMessages[0];
            var attributes = shoutRequestMessage.Message.Attributes;
            string postStatusUrl;
            string postStatusToken;
            DateTime requestDeadline;
            try
            {
                postStatusUrl = attributes["postStatusUrl"];
                postStatusToken = attributes["postStatusToken"];
                long unixDeadline = Convert.ToInt64(attributes["deadline"]);
                requestDeadline = FromUnixTime(unixDeadline);
            }
            catch (Exception e)
            {
                WriteLog("Bad shout request message attributes.\n" + e.ToString(),
                    TraceEventType.Warning);
                Acknowledge(shoutRequestMessage.AckId);
                return -1;
            }

            // Tell the world we are shouting this request.
            PublishStatus(postStatusUrl, postStatusToken, "shouting");
            WriteLog("Shouting " + postStatusUrl, TraceEventType.Verbose);

            try
            {
                // Decode the payload, the string we want to shout.
                byte[] data = Convert.FromBase64String(shoutRequestMessage.Message.Data);
                string decodedString = Encoding.UTF8.GetString(data);

                // Watch the clock and cancellation token as we work.  We need to extend the
                // ack deadline if the request takes a while.
                var tenSeconds = TimeSpan.FromSeconds(10);
                DateTime ackDeadline = DateTime.UtcNow + tenSeconds;
                ThrowIfAborted throwIfAborted = () =>
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var now = DateTime.UtcNow;
                    if (requestDeadline < now)
                        throw new FatalException("Request timed out.");
                    if (ackDeadline < now)
                    {
                        // Tell the subscription we need more time:
                        WriteLog("Need more time...", TraceEventType.Verbose);
                        _init.PubsubService.Projects.Subscriptions.ModifyAckDeadline(
                            new ModifyAckDeadlineRequest
                            {
                                AckIds = new string[] { shoutRequestMessage.AckId },
                                AckDeadlineSeconds = 15,
                            }, MakeSubscriptionPath(_init.SubscriptionName)).Execute();
                        ackDeadline = now + tenSeconds;
                    }
                };

                // Shout it.
                string upperText = ShoutString(decodedString, throwIfAborted);

                // Publish the result.
                PublishStatus(postStatusUrl, postStatusToken, "success", upperText);
                Acknowledge(shoutRequestMessage.AckId);
                return 1;
            }
            catch (OperationCanceledException)
            {
                return 1;  // Service stopped.  Nothing to report.
            }
            catch (FatalException e)
            {
                WriteLog("Fatal exception while shouting:\n" + e.Message, TraceEventType.Error);
                Acknowledge(shoutRequestMessage.AckId);
                PublishStatus(postStatusUrl, postStatusToken, "fatal", e.Message);
                return -1;
            }
            catch (Exception e)
            {
                // Something went wrong while shouting.  Report the error.
                WriteLog("Exception while shouting:\n" + e.Message, TraceEventType.Error);
                PublishStatus(postStatusUrl, postStatusToken, "error", e.Message);
                return -1;
            }
        }