Exemplo n.º 1
0
        public async IAsyncEnumerable <JobResult> CreateSnapshotJobsAsync(RuleContext context,
                                                                          [EnumeratorCancellation] CancellationToken ct = default)
        {
            Guard.NotNull(context.Rule, nameof(context.Rule));

            var rule = context.Rule;

            if (!rule.IsEnabled)
            {
                yield break;
            }

            if (!ruleTriggerHandlers.TryGetValue(rule.Trigger.GetType(), out var triggerHandler))
            {
                yield break;
            }

            if (!ruleActionHandlers.TryGetValue(rule.Action.GetType(), out var actionHandler))
            {
                yield break;
            }

            if (!triggerHandler.CanCreateSnapshotEvents)
            {
                yield break;
            }

            var now = clock.GetCurrentInstant();

            await foreach (var enrichedEvent in triggerHandler.CreateSnapshotEventsAsync(context, ct))
            {
                JobResult?job;
                try
                {
                    await eventEnricher.EnrichAsync(enrichedEvent, null);

                    if (!triggerHandler.Trigger(enrichedEvent, context))
                    {
                        continue;
                    }

                    job = await CreateJobAsync(actionHandler, enrichedEvent, context, now);
                }
                catch (Exception ex)
                {
                    job = new JobResult(null, ex);
                }

                yield return(job);
            }
        }
Exemplo n.º 2
0
        public async IAsyncEnumerable <(RuleJob?Job, Exception?Exception)> CreateSnapshotJobsAsync(Rule rule, DomainId ruleId, DomainId appId)
        {
            if (!rule.IsEnabled)
            {
                yield break;
            }

            if (!ruleTriggerHandlers.TryGetValue(rule.Trigger.GetType(), out var triggerHandler))
            {
                yield break;
            }

            if (!ruleActionHandlers.TryGetValue(rule.Action.GetType(), out var actionHandler))
            {
                yield break;
            }

            if (!triggerHandler.CanCreateSnapshotEvents)
            {
                yield break;
            }

            var now = clock.GetCurrentInstant();

            await foreach (var enrichedEvent in triggerHandler.CreateSnapshotEvents(rule.Trigger, appId))
            {
                Exception?exception;

                RuleJob?job = null;

                try
                {
                    await eventEnricher.EnrichAsync(enrichedEvent, null);

                    if (!triggerHandler.Trigger(enrichedEvent, rule.Trigger))
                    {
                        continue;
                    }

                    (job, exception) = await CreateJobAsync(rule, ruleId, actionHandler, now, enrichedEvent);
                }
                catch (Exception ex)
                {
                    exception = ex;
                }

                yield return(job, exception);
            }
        }
Exemplo n.º 3
0
        public RuleServiceTests()
        {
            typeNameRegistry.Map(typeof(ContentCreated));
            typeNameRegistry.Map(typeof(WebhookAction));

            A.CallTo(() => eventEnricher.EnrichAsync(A <Envelope <AppEvent> > .Ignored))
            .Returns(new EnrichedContentEvent());

            A.CallTo(() => ruleActionHandler.ActionType)
            .Returns(typeof(WebhookAction));

            A.CallTo(() => ruleTriggerHandler.TriggerType)
            .Returns(typeof(ContentChangedTrigger));

            sut = new RuleService(new[] { ruleTriggerHandler }, new[] { ruleActionHandler }, eventEnricher, clock, typeNameRegistry);
        }
Exemplo n.º 4
0
        public async Task Should_create_job_if_triggered()
        {
            var now = clock.GetCurrentInstant();

            var rule = ValidRule();

            var enrichedEvent = new EnrichedContentEvent {
                AppId = appId
            };

            var @event = Envelope.Create(new ContentCreated()).SetTimestamp(now);

            A.CallTo(() => ruleTriggerHandler.Trigger(@event.Payload, rule.Trigger, ruleId))
            .Returns(true);

            A.CallTo(() => ruleTriggerHandler.Trigger(enrichedEvent, rule.Trigger))
            .Returns(true);

            A.CallTo(() => ruleTriggerHandler.CreateEnrichedEventAsync(A <Envelope <AppEvent> > .That.Matches(x => x.Payload == @event.Payload)))
            .Returns(enrichedEvent);

            A.CallTo(() => ruleActionHandler.CreateJobAsync(A <EnrichedEvent> .Ignored, rule.Action))
            .Returns((actionDescription, new ValidData {
                Value = 10
            }));

            var job = await sut.CreateJobAsync(rule, ruleId, @event);

            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(enrichedEvent.AppId.Id, job.AppId);

            Assert.NotEqual(Guid.Empty, job.JobId);

            A.CallTo(() => eventEnricher.EnrichAsync(enrichedEvent, A <Envelope <AppEvent> > .That.Matches(x => x.Payload == @event.Payload)))
            .MustHaveHappened();
        }
Exemplo n.º 5
0
        public virtual async Task <RuleJob> CreateJobAsync(Rule rule, Envelope <IEvent> @event)
        {
            Guard.NotNull(rule, nameof(rule));
            Guard.NotNull(@event, nameof(@event));

            if (!rule.IsEnabled)
            {
                return(null);
            }

            if (!(@event.Payload is AppEvent appEvent))
            {
                return(null);
            }

            var actionType = rule.Action.GetType();

            if (!ruleTriggerHandlers.TryGetValue(rule.Trigger.GetType(), out var triggerHandler))
            {
                return(null);
            }

            if (!ruleActionHandlers.TryGetValue(actionType, out var actionHandler))
            {
                return(null);
            }

            var appEventEnvelope = @event.To <AppEvent>();

            if (!triggerHandler.Triggers(appEventEnvelope, rule.Trigger))
            {
                return(null);
            }

            var now = clock.GetCurrentInstant();

            var eventTime =
                @event.Headers.ContainsKey(CommonHeaders.Timestamp) ?
                @event.Headers.Timestamp() :
                now;

            var expires = eventTime.Plus(Constants.ExpirationTime);

            if (expires < now)
            {
                return(null);
            }

            var enrichedEvent = await eventEnricher.EnrichAsync(appEventEnvelope);

            var actionName = typeNameRegistry.GetName(actionType);
            var actionData = await actionHandler.CreateJobAsync(enrichedEvent, rule.Action);

            var json = jsonSerializer.Serialize(actionData.Data);

            var job = new RuleJob
            {
                JobId       = Guid.NewGuid(),
                ActionName  = actionName,
                ActionData  = json,
                AggregateId = enrichedEvent.AggregateId,
                AppId       = appEvent.AppId.Id,
                Created     = now,
                EventName   = enrichedEvent.Name,
                Expires     = expires,
                Description = actionData.Description
            };

            return(job);
        }
Exemplo n.º 6
0
        public virtual async Task <RuleJob> CreateJobAsync(Rule rule, Guid ruleId, Envelope <IEvent> @event)
        {
            Guard.NotNull(rule, nameof(rule));
            Guard.NotNull(@event, nameof(@event));

            try
            {
                if (!rule.IsEnabled)
                {
                    return(null);
                }

                if (!(@event.Payload is AppEvent))
                {
                    return(null);
                }

                var typed = @event.To <AppEvent>();

                var actionType = rule.Action.GetType();

                if (!ruleTriggerHandlers.TryGetValue(rule.Trigger.GetType(), out var triggerHandler))
                {
                    return(null);
                }

                if (!ruleActionHandlers.TryGetValue(actionType, out var actionHandler))
                {
                    return(null);
                }

                var now = clock.GetCurrentInstant();

                var eventTime =
                    @event.Headers.ContainsKey(CommonHeaders.Timestamp) ?
                    @event.Headers.Timestamp() :
                    now;

                var expires = eventTime.Plus(Constants.ExpirationTime);

                if (expires < now)
                {
                    return(null);
                }

                if (!triggerHandler.Trigger(typed.Payload, rule.Trigger, ruleId))
                {
                    return(null);
                }

                var appEventEnvelope = @event.To <AppEvent>();

                var enrichedEvent = await triggerHandler.CreateEnrichedEventAsync(appEventEnvelope);

                if (enrichedEvent == null)
                {
                    return(null);
                }

                await eventEnricher.EnrichAsync(enrichedEvent, typed);

                if (!triggerHandler.Trigger(enrichedEvent, rule.Trigger))
                {
                    return(null);
                }

                var actionName = typeNameRegistry.GetName(actionType);
                var actionData = await actionHandler.CreateJobAsync(enrichedEvent, rule.Action);

                var json = jsonSerializer.Serialize(actionData.Data);

                var job = new RuleJob
                {
                    JobId              = Guid.NewGuid(),
                    ActionName         = actionName,
                    ActionData         = json,
                    AppId              = enrichedEvent.AppId.Id,
                    Created            = now,
                    EventName          = enrichedEvent.Name,
                    ExecutionPartition = enrichedEvent.Partition,
                    Expires            = expires,
                    Description        = actionData.Description
                };

                return(job);
            }
            catch (Exception ex)
            {
                log.LogError(ex, w => w
                             .WriteProperty("action", "createRuleJob")
                             .WriteProperty("status", "Failed"));

                return(null);
            }
        }
Exemplo n.º 7
0
        public virtual async Task <JobList> CreateJobsAsync(Rule rule, DomainId ruleId, Envelope <IEvent> @event, bool ignoreStale = true)
        {
            Guard.NotNull(rule, nameof(rule));
            Guard.NotNull(@event, nameof(@event));

            var result = new JobList();

            try
            {
                if (!rule.IsEnabled)
                {
                    return(result);
                }

                if (!(@event.Payload is AppEvent))
                {
                    return(result);
                }

                var typed = @event.To <AppEvent>();

                if (typed.Payload.FromRule)
                {
                    return(result);
                }

                var actionType = rule.Action.GetType();

                if (!ruleTriggerHandlers.TryGetValue(rule.Trigger.GetType(), out var triggerHandler))
                {
                    return(result);
                }

                if (!ruleActionHandlers.TryGetValue(actionType, out var actionHandler))
                {
                    return(result);
                }

                var now = clock.GetCurrentInstant();

                var eventTime =
                    @event.Headers.ContainsKey(CommonHeaders.Timestamp) ?
                    @event.Headers.Timestamp() :
                    now;

                if (ignoreStale && eventTime.Plus(Constants.StaleTime) < now)
                {
                    return(result);
                }

                var expires = now.Plus(Constants.ExpirationTime);

                if (!triggerHandler.Trigger(typed.Payload, rule.Trigger, ruleId))
                {
                    return(result);
                }

                var appEventEnvelope = @event.To <AppEvent>();

                var enrichedEvents = await triggerHandler.CreateEnrichedEventsAsync(appEventEnvelope);

                foreach (var enrichedEvent in enrichedEvents)
                {
                    try
                    {
                        await eventEnricher.EnrichAsync(enrichedEvent, typed);

                        if (!triggerHandler.Trigger(enrichedEvent, rule.Trigger))
                        {
                            continue;
                        }

                        var actionName = typeNameRegistry.GetName(actionType);

                        var job = new RuleJob
                        {
                            Id                 = DomainId.NewGuid(),
                            ActionData         = string.Empty,
                            ActionName         = actionName,
                            AppId              = enrichedEvent.AppId.Id,
                            Created            = now,
                            EventName          = enrichedEvent.Name,
                            ExecutionPartition = enrichedEvent.Partition,
                            Expires            = expires,
                            RuleId             = ruleId
                        };

                        try
                        {
                            var(description, data) = await actionHandler.CreateJobAsync(enrichedEvent, rule.Action);

                            var json = jsonSerializer.Serialize(data);

                            job.ActionData  = json;
                            job.ActionName  = actionName;
                            job.Description = description;

                            result.Add((job, null));
                        }
                        catch (Exception ex)
                        {
                            job.Description = "Failed to create job";

                            result.Add((job, ex));
                        }
                    }
                    catch (Exception ex)
                    {
                        log.LogError(ex, w => w
                                     .WriteProperty("action", "createRuleJobFromEvent")
                                     .WriteProperty("status", "Failed"));
                    }
                }
            }
            catch (Exception ex)
            {
                log.LogError(ex, w => w
                             .WriteProperty("action", "createRuleJob")
                             .WriteProperty("status", "Failed"));
            }

            return(result);
        }