示例#1
0
        public void Should_not_create_job_if_too_old()
        {
            var e = new ContentCreated {
                SchemaId = new NamedId <Guid>(Guid.NewGuid(), "my-schema"), AppId = new NamedId <Guid>(Guid.NewGuid(), "my-event")
            };

            var now = SystemClock.Instance.GetCurrentInstant();

            var ruleConfig   = new Rule(new ContentChangedTrigger(), new WebhookAction());
            var ruleEnvelope = Envelope.Create(e);

            ruleEnvelope.SetTimestamp(now.Minus(Duration.FromDays(3)));

            var actionData        = new RuleJobData();
            var actionDescription = "MyDescription";

            var eventName = "MySchemaCreatedEvent";

            A.CallTo(() => clock.GetCurrentInstant())
            .Returns(now);

            A.CallTo(() => ruleTriggerHandler.Triggers(A <Envelope <AppEvent> > .Ignored, ruleConfig.Trigger))
            .Returns(true);

            A.CallTo(() => ruleActionHandler.CreateJob(A <Envelope <AppEvent> > .Ignored, eventName, ruleConfig.Action))
            .Returns((actionDescription, actionData));

            var job = sut.CreateJob(ruleConfig, ruleEnvelope);

            Assert.Null(job);
        }
示例#2
0
        public void Should_set_next_attempt_based_on_num_calls(int calls, int minutes, RuleResult result, RuleJobResult jobResult)
        {
            var actionData = new RuleJobData();
            var actionName = "MyAction";

            var @event = CreateEvent(calls, actionName, actionData);

            var requestElapsed = TimeSpan.FromMinutes(1);
            var requestDump    = "Dump";

            SetupSender(@event, requestDump, result, requestElapsed);
            SetupPendingEvents(@event);

            var sut = new RuleDequeuer(
                ruleService,
                ruleEventRepository,
                log,
                clock);

            sut.Next();
            sut.Dispose();

            Instant?nextCall = null;

            if (minutes > 0)
            {
                nextCall = now.Plus(Duration.FromMinutes(minutes));
            }

            VerifyRepositories(@event, requestDump, result, jobResult, requestElapsed, nextCall);
        }
示例#3
0
        public async Task Should_set_next_attempt_based_on_num_calls(int calls, int minutes, RuleResult result, RuleJobResult jobResult)
        {
            var actionData = new RuleJobData();
            var actionName = "MyAction";

            var @event = CreateEvent(calls, actionName, actionData);

            var requestElapsed = TimeSpan.FromMinutes(1);
            var requestDump    = "Dump";

            A.CallTo(() => ruleService.InvokeAsync(@event.Job.ActionName, @event.Job.ActionData))
            .Returns((requestDump, result, requestElapsed));

            Instant?nextCall = null;

            if (minutes > 0)
            {
                nextCall = now.Plus(Duration.FromMinutes(minutes));
            }

            await sut.HandleAsync(@event);

            A.CallTo(() => ruleEventRepository.MarkSentAsync(@event.Id, requestDump, result, jobResult, requestElapsed, nextCall))
            .MustHaveHappened();
        }
示例#4
0
        public async Task Should_create_exception_details_when_job_to_execute_failed()
        {
            var ruleJob = new RuleJobData();
            var ruleEx  = new InvalidOperationException();

            A.CallTo(() => ruleActionHandler.ExecuteJobAsync(ruleJob))
            .Throws(ruleEx);

            var result = await sut.InvokeAsync("WebhookAction", ruleJob);

            Assert.Equal((ruleEx.ToString(), RuleResult.Failed, TimeSpan.Zero), result);
        }
示例#5
0
        protected override (string Description, RuleJobData Data) CreateJob(Envelope <AppEvent> @event, string eventName, SlackAction action)
        {
            var body = CreatePayload(@event, action.Text);

            var ruleDescription = "Send message to slack";
            var ruleData        = new RuleJobData
            {
                ["RequestUrl"]  = action.WebhookUrl,
                ["RequestBody"] = body
            };

            return(ruleDescription, ruleData);
        }
示例#6
0
        protected override (string Description, RuleJobData Data) CreateJob(Envelope <AppEvent> @event, string eventName, WebhookAction action)
        {
            var body = formatter.ToRouteData(@event, eventName);

            var signature = $"{body.ToString(Formatting.Indented)}{action.SharedSecret}".Sha256Base64();

            var ruleDescription = $"Send event to webhook '{action.Url}'";
            var ruleData        = new RuleJobData
            {
                ["RequestUrl"]       = action.Url,
                ["RequestBody"]      = body,
                ["RequestSignature"] = signature
            };

            return(ruleDescription, ruleData);
        }
示例#7
0
        protected override (string Description, RuleJobData Data) CreateJob(Envelope <AppEvent> @event, string eventName, FastlyAction action)
        {
            var ruleDescription = "Purge key in fastly";
            var ruleData        = new RuleJobData
            {
                ["FastlyApiKey"]    = action.ApiKey,
                ["FastlyServiceID"] = action.ServiceId
            };

            if (@event.Headers.Contains(CommonHeaders.AggregateId))
            {
                ruleData["Key"] = @event.Headers.AggregateId().ToString();
            }

            return(ruleDescription, ruleData);
        }
示例#8
0
        public async Task Should_return_failed_job_with_full_dump_when_handler_returns_exception()
        {
            var ruleJob = new RuleJobData();
            var ruleEx  = new InvalidOperationException();

            var actionDump = "MyDump";

            A.CallTo(() => ruleActionHandler.ExecuteJobAsync(ruleJob))
            .Returns((actionDump, new InvalidOperationException()));

            var result = await sut.InvokeAsync("WebhookAction", ruleJob);

            Assert.Equal(RuleResult.Failed, result.Result);

            Assert.True(result.Elapsed >= TimeSpan.Zero);
            Assert.True(result.Dump.StartsWith(actionDump, StringComparison.OrdinalIgnoreCase));
        }
示例#9
0
        public void Should_create_job_if_triggered()
        {
            var e = new ContentCreated {
                SchemaId = new NamedId <Guid>(Guid.NewGuid(), "my-schema"), AppId = new NamedId <Guid>(Guid.NewGuid(), "my-event")
            };

            var now = SystemClock.Instance.GetCurrentInstant();

            var ruleConfig   = new Rule(new ContentChangedTrigger(), new WebhookAction());
            var ruleEnvelope = Envelope.Create(e);

            ruleEnvelope.SetTimestamp(now);

            var actionName        = "WebhookAction";
            var actionData        = new RuleJobData();
            var actionDescription = "MyDescription";

            var eventName = "MySchemaCreatedEvent";

            A.CallTo(() => clock.GetCurrentInstant())
            .Returns(now);

            A.CallTo(() => ruleTriggerHandler.Triggers(A <Envelope <AppEvent> > .Ignored, ruleConfig.Trigger))
            .Returns(true);

            A.CallTo(() => ruleActionHandler.CreateJob(A <Envelope <AppEvent> > .Ignored, eventName, ruleConfig.Action))
            .Returns((actionDescription, actionData));

            var job = sut.CreateJob(ruleConfig, ruleEnvelope);

            Assert.Equal(eventName, job.EventName);

            Assert.Equal(actionData, job.ActionData);
            Assert.Equal(actionName, job.ActionName);
            Assert.Equal(actionDescription, job.Description);

            Assert.Equal(now, job.Created);
            Assert.Equal(now.Plus(Duration.FromDays(2)), job.Expires);

            Assert.Equal(e.AppId.Id, job.AppId);

            Assert.NotEqual(Guid.Empty, job.JobId);
        }
示例#10
0
        private IRuleEventEntity CreateEvent(int numCalls, string actionName, RuleJobData actionData)
        {
            var @event = A.Fake <IRuleEventEntity>();

            var job = new RuleJob
            {
                RuleId     = Guid.NewGuid(),
                ActionData = actionData,
                ActionName = actionName,
                Created    = now
            };

            A.CallTo(() => @event.Id).Returns(Guid.NewGuid());
            A.CallTo(() => @event.Job).Returns(job);
            A.CallTo(() => @event.Created).Returns(now);
            A.CallTo(() => @event.NumCalls).Returns(numCalls);

            return(@event);
        }
示例#11
0
        public virtual async Task <(string Dump, RuleResult Result, TimeSpan Elapsed)> InvokeAsync(string actionName, RuleJobData job)
        {
            try
            {
                var actionType  = typeNameRegistry.GetType(actionName);
                var actionWatch = Stopwatch.StartNew();

                var result = await ruleActionHandlers[actionType].ExecuteJobAsync(job);

                actionWatch.Stop();

                var dumpBuilder = new StringBuilder(result.Dump);

                dumpBuilder.AppendLine();
                dumpBuilder.AppendFormat("Elapsed {0}.", actionWatch.Elapsed);
                dumpBuilder.AppendLine();

                if (result.Exception is TimeoutException || result.Exception is OperationCanceledException)
                {
                    dumpBuilder.AppendLine();
                    dumpBuilder.AppendLine("Action timed out.");

                    return(dumpBuilder.ToString(), RuleResult.Timeout, actionWatch.Elapsed);
                }
                else if (result.Exception != null)
                {
                    return(dumpBuilder.ToString(), RuleResult.Failed, actionWatch.Elapsed);
                }
                else
                {
                    return(dumpBuilder.ToString(), RuleResult.Success, actionWatch.Elapsed);
                }
            }
            catch (Exception ex)
            {
                return(ex.ToString(), RuleResult.Failed, TimeSpan.Zero);
            }
        }
示例#12
0
        public override async Task <(string Dump, Exception Exception)> ExecuteJobAsync(RuleJobData job)
        {
            var requestBody = job["RequestBody"].ToString(Formatting.Indented);
            var requestMsg  = BuildRequest(job, requestBody);

            HttpResponseMessage response = null;

            try
            {
                response = await HttpClientPool.GetHttpClient().SendAsync(requestMsg);

                var responseString = await response.Content.ReadAsStringAsync();

                var requestDump = DumpFormatter.BuildDump(requestMsg, response, requestBody, responseString, TimeSpan.Zero, false);

                Exception ex = null;

                if (!response.IsSuccessStatusCode)
                {
                    ex = new HttpRequestException($"Response code does not indicate success: {(int)response.StatusCode} ({response.StatusCode}).");
                }

                return(requestDump, ex);
            }
            catch (Exception ex)
            {
                if (requestMsg != null)
                {
                    var requestDump = DumpFormatter.BuildDump(requestMsg, response, requestBody, ex.ToString(), TimeSpan.Zero, false);

                    return(requestDump, ex);
                }
                else
                {
                    throw;
                }
            }
        }
示例#13
0
        public override async Task <(string Dump, Exception Exception)> ExecuteJobAsync(RuleJobData job)
        {
            if (!job.TryGetValue("Key", out var keyToken))
            {
                return(null, new InvalidOperationException("The action cannot handle this event."));
            }

            var requestMsg = BuildRequest(job, keyToken.Value <string>());

            HttpResponseMessage response = null;

            try
            {
                response = await HttpClientPool.GetHttpClient().SendAsync(requestMsg);

                var responseString = await response.Content.ReadAsStringAsync();

                var requestDump = DumpFormatter.BuildDump(requestMsg, response, null, responseString, TimeSpan.Zero, false);

                return(requestDump, null);
            }
            catch (Exception ex)
            {
                if (requestMsg != null)
                {
                    var requestDump = DumpFormatter.BuildDump(requestMsg, response, null, ex.ToString(), TimeSpan.Zero, false);

                    return(requestDump, ex);
                }
                else
                {
                    var requestDump = ex.ToString();

                    return(requestDump, ex);
                }
            }
        }
示例#14
0
        public override async Task <(string Dump, Exception Exception)> ExecuteJobAsync(RuleJobData job)
        {
            var requestBody = job["RequestBody"].ToString(Formatting.Indented);
            var request     = BuildRequest(job, requestBody);

            HttpResponseMessage response = null;

            try
            {
                using (var client = new HttpClient {
                    Timeout = Timeout
                })
                {
                    response = await client.SendAsync(request);

                    var responseString = await response.Content.ReadAsStringAsync();

                    var requestDump = DumpFormatter.BuildDump(request, response, requestBody, responseString, TimeSpan.Zero, false);

                    return(requestDump, null);
                }
            }
            catch (Exception ex)
            {
                if (request != null)
                {
                    var requestDump = DumpFormatter.BuildDump(request, response, requestBody, ex.ToString(), TimeSpan.Zero, false);

                    return(requestDump, ex);
                }
                else
                {
                    var requestDump = ex.ToString();

                    return(requestDump, ex);
                }
            }
        }
示例#15
0
        public override async Task <(string Dump, Exception Exception)> ExecuteJobAsync(RuleJobData job)
        {
            var requestBody = job["RequestBody"].ToString(Formatting.Indented);
            var requestMsg  = BuildRequest(job, requestBody);

            HttpResponseMessage response = null;

            try
            {
                response = await HttpClientPool.GetHttpClient().SendAsync(requestMsg);

                var responseString = await response.Content.ReadAsStringAsync();

                var requestDump = DumpFormatter.BuildDump(requestMsg, response, requestBody, responseString, TimeSpan.Zero, false);

                return(requestDump, null);
            }
            catch (Exception ex)
            {
                if (requestMsg != null)
                {
                    var requestDump = DumpFormatter.BuildDump(requestMsg, response, requestBody, ex.ToString(), TimeSpan.Zero, false);

                    return(requestDump, ex);
                }
                else
                {
                    throw;
                }
            }
        }