Skip to content

End To End Flow

1. Happy Path

DEC

The initial activities come from CPP, which produces them to a topic called {{ dc }}.{{ brand }}.cpp.activity. Once consumed by DEC, these activities are converted to DEC's domain object, CPPActivity.

DEC then calls the service PPH with the promoCode, and PPH returns some extra static information regarding that promotion, which allows DEC to enrich the different rewardProgress that a single CPPActivity object can have with products, rewardType, productRewardType, tierDefinition and expirationDate of the matching rewardScheme coming from PPH. PromoName, promoUrl, tags and brand are also enriched in the CPPActivity object itself.

The enriched CPPActivity objects are then converted to JSON and put inside a CloudEvent (a kind of wrapper object, you can think of it like an envelope) with some metadata that identifies the contained CPPActivity object (timestamps, id, type, source, subject and brand) without the need to deserialise the CPPActivity object, and they are produced to the Kafka topic {{ brand }}.cpp.enriched.events cloudEvent.png

In all of our applications, timestamps are propagated by using a binder that wraps the domain object and either an object that stores timestamps or the CloudEvent wrapper it came from (also containing the timestamps as metadata), which will then be used to create the new CloudEvent by coping over the data. These timestamps allow us to get metrics and give us an idea of how long the whole or a part of the flow takes at any given time. All these wrapper classes exist in the common library

TIM

TIM consumes the data produced by DEC, and filters the relevant ones by their tags (defined as TIM_FILTER_TAG in the environment configMap). Then, they are keyed by the accountId, promoCode and attemptId, which allows TIM to keep a state and retrieve those values by their keys (this state is persisted using RocksDB). This allows TIM to make sure that when the same event comes in more than once, we will ignore the subsequent events instead of propagating them again (deduping stage).

The logic inside TIM's RewardStateProcessor for different event statuses: timRewardStateProcess.png

The processed events are then separated by their tags into regular events or unqualification events and put into CloudEvents once more before being produced to the output topic {{ brand }}.relevant.events.

https://miro.com/app/board/uXjVKv-MmDM=/

FRED

FRED receives the events from upstream and filters them based on the config. If according to the config the event needs to be processed further, it would call DES to get a decision. Once it gets the decision back, if the has-decision header is set to 'true', this event will be sent to BCG.

DES

Takes each RewardProgress in the CloudEvent data, and if the activityType is either "FREE_SPINS", "FREE_BET" or "GAMING_BONUS", a DECISION is returned for that CloudEvent, otherwise, the STATUS in the CloudEvent returned will be NO_DECISION. DES includes the delivery preferences for message type (e.g. toast/full screen). The response from DES has a has-decision header set to 'true' or 'false', so that FRED doesn't need to deserialise it.

BCG, OSG & MSQ

BCG filters and removes expired messages as well as those lacking a delivery preference. Onsite message content is resolved by retrieving message templates from Prismic via CSL. BCG will send an onsite message to OSG, which will respond with a 200 code if the customer was onsite and message was delivered or a 404 if the customer is not on-site and the message couldn't be delivered. In the later case, the message is queued in MSQ. Queued messages are stored in a Dynamo DB before being resent when a customer comes back online.

For the REWARD_AWARDED message only, once it gets to the new cycle on Monday, BCG doesn’t try to send it directly to OSG, and instead it always goes to the queue. This is not to interrupt customer journey with a full screen message. For UNQUALIFICATION, it will go through to OSG.

2. Customer spends reward before message has been seen

This scenario shouldn't really be possible for SBG since messages will be received in both desktop and mobile when the customer is online, but can happen for other flavours. In this case, a DeleteMessageInstruction is produced in TIM to the topic msq.inbound.delete.{{ env }}, so that MSQ deletes the REWARD_AWARDED message from the queue and the customer doesn't receive it (since we consider they are already aware of the reward).

3. Customer doesn't qualify for week one

These messages come from the topic {{ dc }}.{{ brand }}.eppm.activity. DEC has a specific EPPM processor for the Week One Unqualification. These messages will be produced to the topic {{ brand }}.relevant.unqualification.events which is directly consumed by FRED (skipping TIM since no filtering is necessary).

4. Customer doesn't qualify for week two

These messages come from the same topic as activity progress messages ({{ dc }}.{{ brand }}.cpp.activity) and are consumed by the cpp-activity-consumer in DEC. These messages will be produced to the topic {{ brand }}.cpp.enriched.events and sent to TIM, which will filter these messages to a separate output and send them to FRED to continue a similar flow as in the happy path.

End2EndFlow