Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Historical lookup indexed db #1048

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e3a129c
new branch for indexedDB storage
shandilya3 Sep 15, 2023
c9d7217
CJM-53824
jasonwaters Sep 15, 2023
7bd4b21
fix message feed ids and conditions
jasonwaters Sep 20, 2023
d7b6f5b
fix message feed ids and conditions
jasonwaters Sep 20, 2023
824e3dd
Introduce indexedDB registry
shandilya3 Sep 29, 2023
139cb51
Introduce indexedDB registry
shandilya3 Oct 1, 2023
34415ef
Introduce indexedDB registry
shandilya3 Oct 2, 2023
df36999
Introduce indexedDB registry
shandilya3 Oct 2, 2023
85a96f0
not using regenerator-runtime
shandilya3 Oct 2, 2023
95c1ae0
use action
shandilya3 Oct 2, 2023
1e87456
fix for trigger frequency show message on specific hourofday
shandilya3 Oct 2, 2023
3c69ae3
clean up, keeping just eventRegistry as before
shandilya3 Oct 2, 2023
2a63ff5
fixed tests
shandilya3 Oct 3, 2023
e6b634c
should move indexedDB setup in it's dedicated module
shandilya3 Oct 3, 2023
93e794a
test fix progress
shandilya3 Oct 3, 2023
8e6d165
restoring the functional tests
shandilya3 Oct 3, 2023
5b4d507
support day of week and hour as described in authoring ui
shandilya3 Oct 3, 2023
ebbac68
moved indexedJS creation in a dedicated module
shandilya3 Oct 5, 2023
82974d5
clean
shandilya3 Oct 5, 2023
697cd95
clean
shandilya3 Oct 5, 2023
ed2f086
clean
shandilya3 Oct 5, 2023
e325e3d
Reverting back to original sandbox code for In-app as the latest one …
shandilya3 Oct 5, 2023
7e4898a
test fix
shandilya3 Oct 5, 2023
af85cd4
test fix & some clean up
shandilya3 Oct 9, 2023
f7e6e14
IAM - Sandbox in sync with feature branch
shandilya3 Oct 10, 2023
8145d9e
use activityID to save the ruleset&conditions
shandilya3 Oct 10, 2023
7711eb4
fixed test
shandilya3 Oct 10, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
}
],
"dependencies": {
"@adobe/aep-rules-engine": "^2.0.1",
"@adobe/aep-rules-engine": "file:../aepsdk-rulesengine-typescript",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for local e2e test, will add dependency once rule engine changes are approved & published.

"@adobe/reactor-cookie": "^1.0.0",
"@adobe/reactor-load-script": "^1.1.1",
"@adobe/reactor-object-assign": "^1.0.0",
Expand Down
28 changes: 9 additions & 19 deletions sandbox/src/components/MessageFeedDemo/MessageFeed.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const mockResponse = {
],
activity: {
id:
"39ae8d4b-b55e-43dc-a143-77f50195b487#b47fde8b-57c1-4bbe-ae22-64d5b782d183"
"8e24e51d-5203-4d0b-99c9-2b3c95ff48f2#05885219-ea84-43bc-874e-1ef4a85b6fbb"
},
correlationID: "02c77ea8-7c0e-4d33-8090-4a5bfd3d7503"
},
Expand Down Expand Up @@ -148,7 +148,7 @@ const mockResponse = {
],
activity: {
id:
"39ae8d4b-b55e-43dc-a143-77f50195b487#b47fde8b-57c1-4bbe-ae22-64d5b782d183"
"cf087a6e-131d-4147-adc7-bc1ea947f09c#ff64e6e6-e43f-479d-b5c0-f5568c771b3b"
},
correlationID: "02c77ea8-7c0e-4d33-8090-4a5bfd3d7503"
},
Expand Down Expand Up @@ -179,9 +179,9 @@ const mockResponse = {
definition: {
events: [
{
type: "decisioning.propositionDisplay",
id:
"1ae11bc5-96dc-41c7-8f71-157c57a5290e"
"iam.eventType": "display",
"iam.id":
"cf087a6e-131d-4147-adc7-bc1ea947f09c#ff64e6e6-e43f-479d-b5c0-f5568c771b3b"
}
],
matcher: "ge",
Expand Down Expand Up @@ -251,7 +251,7 @@ const mockResponse = {
],
activity: {
id:
"39ae8d4b-b55e-43dc-a143-77f50195b487#b47fde8b-57c1-4bbe-ae22-64d5b782d183"
"57712381-1690-4d19-9469-0a35ea5bd4e3#74f8e5cf-d770-41c3-b595-557b3ee00ba3"
},
correlationID: "02c77ea8-7c0e-4d33-8090-4a5bfd3d7503"
},
Expand Down Expand Up @@ -282,9 +282,9 @@ const mockResponse = {
definition: {
events: [
{
type: "decisioning.propositionDisplay",
id:
"d1f7d411-a549-47bc-a4d8-c8e638b0a46b"
"iam.eventType": "trigger",
"iam.id":
"57712381-1690-4d19-9469-0a35ea5bd4e3#74f8e5cf-d770-41c3-b595-557b3ee00ba3"
}
],
matcher: "ge",
Expand Down Expand Up @@ -424,7 +424,6 @@ export default function MessageFeed() {
surface: "web://target.jasonwaters.dev/aep.html",
callback: ({ items = [], rendered, clicked }) => {
setClickHandler(() => clicked);

setMessageFeedItems(items);
rendered(items);
}
Expand Down Expand Up @@ -453,12 +452,6 @@ export default function MessageFeed() {
}
});
};

const resetPersistentData = () => {
localStorage.clear();
window.location.reload();
};

return (
<div>
<ContentSecurityPolicy />
Expand All @@ -469,9 +462,6 @@ export default function MessageFeed() {
<button id="deposit-funds" onClick={() => depositFunds()}>
Deposit funds
</button>
<button id="reset" onClick={() => resetPersistentData()}>
Reset
</button>
</div>
<div style={{ margin: "30px 0" }}>
<h3>Message Feed</h3>
Expand Down
2 changes: 2 additions & 0 deletions src/components/DecisioningEngine/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ export const MOBILE_EVENT_SOURCE = {
LAUNCH: "com.adobe.eventSource.applicationLaunch",
REQUEST: "com.adobe.eventSource.requestContent"
};

export const HISTORICAL_DATA_STORE = "historicalDataStore";
11 changes: 8 additions & 3 deletions src/components/DecisioningEngine/createContextProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ export default ({ eventRegistry, window }) => {
pageLoadTimestamp,
currentTimestamp,
currentDate: now.getDate(),
currentDay: now.getDay(),
currentHour: now.getHours(),
// Day of the week starts on Monday as is practiced in ISO 8601, but we want it to start on Sunday to match the authoring UI rule
"~state.com.adobe.module.lifecycle/lifecyclecontextdata.dayofweek":
now.getDay() + 1,
"~state.com.adobe.module.lifecycle/lifecyclecontextdata.hourofday": now.getHours(),
currentMinute: now.getMinutes(),
currentMonth: now.getMonth(),
currentYear: now.getFullYear(),
Expand Down Expand Up @@ -84,7 +86,10 @@ export default ({ eventRegistry, window }) => {
...addedContext
};

return { ...flattenObject(context), events: eventRegistry.toJSON() };
return {
...flattenObject(context),
events: eventRegistry.getIndexDB()
};
};
return {
getContext
Expand Down
7 changes: 3 additions & 4 deletions src/components/DecisioningEngine/createDecisionHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ OF ANY KIND, either express or implied. See the License for the specific languag
governing permissions and limitations under the License.
*/

const QUALIFIED_EVENT_TYPE = "decisioning.propositionQualified";
import { PropositionEventType } from "../Personalization/constants/propositionEventType";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't allow importing between components in Alloy. If this needs to be shared between the two components, put it into src/shared.


export default ({ eventRegistry }) => {
const recordQualified = item => {
const { id } = item;
const recordQualified = id => {
if (!id) {
return undefined;
}
return eventRegistry.addEvent(item, QUALIFIED_EVENT_TYPE, id);
return eventRegistry.addEvent({}, PropositionEventType.TRIGGER, id);
};

return { recordQualified };
Expand Down
23 changes: 16 additions & 7 deletions src/components/DecisioningEngine/createDecisionProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ governing permissions and limitations under the License.
*/
import createEvaluableRulesetPayload from "./createEvaluableRulesetPayload";
import createDecisionHistory from "./createDecisionHistory";
import { getActivityId } from "./utils";

export default ({ eventRegistry }) => {
const payloads = {};
const payloadsByActivityId = {};

const decisionHistory = createDecisionHistory({ eventRegistry });

const addPayload = payload => {
if (!payload.id) {
const activityId = getActivityId(payload);
if (!activityId) {
return;
}

Expand All @@ -29,14 +31,21 @@ export default ({ eventRegistry }) => {
);

if (evaluableRulesetPayload.isEvaluable) {
payloads[payload.id] = evaluableRulesetPayload;
payloadsByActivityId[activityId] = evaluableRulesetPayload;
}
};

const evaluate = (context = {}) =>
Object.values(payloads)
.map(payload => payload.evaluate(context))
.filter(payload => payload.items.length > 0);
const evaluate = (context = {}) => {
return new Promise(resolve => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wrapping new Promise() is unnecessary and can be removed without effect. Returning something from a .then() is the same as resolving the Promise with that value.

Promise.all(
Object.values(payloadsByActivityId).map(payload =>
payload.evaluate(context)
)
).then(consequences => {
resolve(consequences.filter(payload => payload.items.length > 0));
});
});
};

const addPayloads = personalizationPayloads => {
personalizationPayloads.forEach(addPayload);
Expand Down
74 changes: 48 additions & 26 deletions src/components/DecisioningEngine/createEvaluableRulesetPayload.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import {
JSON_CONTENT_ITEM,
RULESET_ITEM
} from "../Personalization/constants/schema";
import { DISPLAY } from "../Personalization/constants/eventType";
import { PropositionEventType } from "../Personalization/constants/propositionEventType";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as before. If it needs to be shared across components, then it should be in the shared folder.


import flattenArray from "../../utils/flattenArray";
import createConsequenceAdapter from "./createConsequenceAdapter";
import { getActivityId } from "./utils";

const isRulesetItem = item => {
const { schema, data } = item;
Expand All @@ -42,6 +43,7 @@ const isRulesetItem = item => {

export default (payload, eventRegistry, decisionHistory) => {
const consequenceAdapter = createConsequenceAdapter();
const activityId = getActivityId(payload);
const items = [];

const addItem = item => {
Expand All @@ -59,31 +61,51 @@ export default (payload, eventRegistry, decisionHistory) => {
};

const evaluate = context => {
const displayEvent = eventRegistry.getEvent(DISPLAY, payload.id);

const displayedDate = displayEvent
? displayEvent.firstTimestamp
: undefined;

const qualifyingItems = flattenArray(
items.map(item => item.execute(context))
)
.map(consequenceAdapter)
.map(item => {
const {
firstTimestamp: qualifiedDate
} = decisionHistory.recordQualified(item);

return {
...item,
data: { ...item.data, qualifiedDate, displayedDate }
};
});

return {
...payload,
items: qualifyingItems
};
return new Promise(resolve => {
let consequencesFlattened = [];
Promise.all(items.map(item => item.execute(context)))
.then(consequences => {
consequencesFlattened = flattenArray(consequences).map(
consequenceAdapter
);
if (!consequencesFlattened || consequencesFlattened.length === 0) {
resolve({
...payload,
items: []
});
return;
}

decisionHistory.recordQualified(activityId);
})
.then(() =>
Promise.all([
eventRegistry.getEventsFirstTimestamp(
PropositionEventType.DISPLAY,
activityId
),
eventRegistry.getEventsFirstTimestamp(
PropositionEventType.TRIGGER,
activityId
)
])
)
.then(dates => {
const displayedDate = dates[0];
const qualifiedDate = dates[1];
const qualifyingItems = consequencesFlattened.map(item => {
return {
...item,
data: { ...item.data, qualifiedDate, displayedDate }
};
});

resolve({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as before. Wrapping it in new Promise() with the resolve is unnecessary.

...payload,
items: qualifyingItems
});
});
});
};

if (Array.isArray(payload.items)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ const validateOptions = ({ options }) => {

export default ({ contextProvider, decisionProvider }) => {
const run = ({ renderDecisions, decisionContext, applyResponse }) => {
return applyResponse({
renderDecisions,
propositions: decisionProvider.evaluate(
contextProvider.getContext(decisionContext)
)
return new Promise(resolve => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

decisionProvider
.evaluate(contextProvider.getContext(decisionContext))
.then(propositions => {
resolve(applyResponse({ renderDecisions, propositions }));
});
});
};

Expand Down
Loading