Skip to content

Commit 64e46b6

Browse files
authored
records equal to pageSize in trigger (#52)
2.4.1
1 parent abedb1e commit 64e46b6

File tree

8 files changed

+382
-71
lines changed

8 files changed

+382
-71
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.4.1 (October 07, 2022)
2+
* Fixed loop issue when records equal to `Size of Polling Page` and have same `LastModifiedDate` in `Get Updated Objects Polling` trigger
3+
* Update Sailor version to 2.7.0
4+
15
## 2.4.0 (August 30, 2022)
26
* New `Get New and Updated Objects Polling` trigger, old one set to deprecated
37
* Update Sailor version to 2.6.29

component.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "Customer relationship management (CRM) software & cloud computing from the leader in CRM solutions for businesses large & small.",
44
"docsUrl": "https://github.com/elasticio/salesforce-component-v2",
55
"url": "http://www.salesforce.com/",
6-
"version": "2.4.0",
6+
"version": "2.4.1",
77
"authClientTypes": [
88
"oauth2"
99
],
@@ -614,4 +614,4 @@
614614
}
615615
}
616616
}
617-
}
617+
}

lib/triggers/getUpdatedObjectsPolling.js

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@ const timestamp = (date) => new Date(date).getTime();
77
const timeToString = (date) => JSON.stringify(new Date(date)).replace(/"/g, '');
88
const isDateValid = (date) => new Date(date).toString() !== 'Invalid Date';
99
const isNumberNaN = (num) => Number(num).toString() === 'NaN';
10+
const MAX_FETCH = 10000;
1011

1112
exports.process = async function processTrigger(_msg, cfg, snapshot) {
1213
this.logger.info('Start processing "Get Updated Objects Polling" trigger');
1314
const currentTime = new Date();
1415

1516
const {
1617
sobject,
17-
pageSize = 10000,
18+
pageSize = MAX_FETCH,
1819
linkedObjects = [],
1920
emitBehavior = 'emitIndividually',
2021
singlePagePerInterval,
@@ -25,8 +26,8 @@ exports.process = async function processTrigger(_msg, cfg, snapshot) {
2526
if (!endTime) endTime = currentTime;
2627
if (!isDateValid(startTime)) throw new Error('invalid "Start Time" date format, use ISO 8601 Date time utc format - YYYY-MM-DDThh:mm:ssZ');
2728
if (!isDateValid(endTime)) throw new Error('invalid "End Time" date format, use ISO 8601 Date time utc format - YYYY-MM-DDThh:mm:ssZ');
28-
if (pageSize > 10000 || isNumberNaN(pageSize) || Number(pageSize) < 0) throw new Error('"Size of Polling Page" must be valid number between 0 and 10000');
29-
let from = snapshot?.nextStartTime || startTime;
29+
if (pageSize > MAX_FETCH || isNumberNaN(pageSize) || Number(pageSize) < 0) throw new Error(`"Size of Polling Page" must be valid number between 0 and ${MAX_FETCH}`);
30+
const from = snapshot?.nextStartTime || startTime;
3031
const to = endTime || currentTime;
3132
let nextStartTime = currentTime;
3233

@@ -42,45 +43,59 @@ exports.process = async function processTrigger(_msg, cfg, snapshot) {
4243
sobject,
4344
selectedObjects: linkedObjects.reduce((query, obj) => (obj.startsWith('!') ? query : `${query}, ${obj}.*`), '*'),
4445
linkedObjects,
45-
maxFetch: pageSize,
4646
};
4747

4848
let proceed = true;
49+
let hasNextPage = false;
4950
let iteration = 1;
51+
let results = [];
5052
try {
5153
do {
52-
options.whereCondition = `LastModifiedDate >= ${timeToString(from)} AND LastModifiedDate < ${timeToString(to)}`;
53-
54-
let results = await callJSForceMethod.call(this, cfg, 'pollingSelectQuery', options);
55-
this.logger.info(`Polling iteration ${iteration} - ${results.length} results found`);
56-
iteration++;
57-
54+
if (!hasNextPage) {
55+
options.whereCondition = `LastModifiedDate >= ${timeToString(from)} AND LastModifiedDate < ${timeToString(to)}`;
56+
results = await callJSForceMethod.call(this, cfg, 'pollingSelectQuery', options);
57+
this.logger.info(`Polling iteration ${iteration} - ${results.length} results found`);
58+
iteration++;
59+
}
5860
if (results.length !== 0) {
59-
if (results.length === Number(pageSize)) {
60-
const currentResultsLength = results.length;
61-
nextStartTime = results[results.length - 1].LastModifiedDate;
62-
const filteredResults = results.filter((item) => item.LastModifiedDate !== nextStartTime);
63-
if (currentResultsLength - filteredResults.length === 0) {
64-
this.logger.warn(`All results from this iteration have same "LastModifiedDate" - ${timeToString(nextStartTime)}, they will be proceed, but all objects in the next iteration will start from date strictly greater than this`);
65-
nextStartTime = new Date(new Date(nextStartTime).getTime() + 1);
66-
} else {
67-
results = filteredResults;
68-
this.logger.warn(`Founded ${currentResultsLength} results, which is equal to page limit.. New start time - ${timeToString(nextStartTime)}, ${currentResultsLength - results.length} result(s) excluded from this iteration`);
69-
}
70-
from = nextStartTime;
71-
} else {
72-
nextStartTime = currentTime;
73-
await this.emit('snapshot', { nextStartTime });
74-
proceed = false;
61+
nextStartTime = currentTime;
62+
if (singlePagePerInterval && snapshot.lastElementId) {
63+
const lastElement = results.filter((item) => item.Id === snapshot.lastElementId)[0];
64+
const lastElementIndex = results.indexOf(lastElement);
65+
results = results.slice(lastElementIndex + 1);
7566
}
76-
77-
if (emitBehavior === 'fetchPage') {
78-
await this.emit('data', messages.newMessageWithBody({ results }));
79-
} else if (emitBehavior === 'emitIndividually') {
80-
for (const record of results) { await this.emit('data', messages.newMessageWithBody(record)); }
67+
if (results.length === MAX_FETCH) {
68+
nextStartTime = results[results.length - 1].LastModifiedDate;
69+
const filteredResults = results.filter((item) => item.LastModifiedDate === nextStartTime);
70+
results = results.slice(0, MAX_FETCH - filteredResults.length);
8171
}
72+
if (results.length >= Number(pageSize)) {
73+
hasNextPage = true;
74+
const pageResults = results.slice(0, pageSize);
75+
results = results.slice(pageSize);
76+
const lastElementLastModifiedDate = pageResults[pageSize - 1].LastModifiedDate;
77+
const lastElementId = pageResults[pageSize - 1].Id;
78+
if (emitBehavior === 'fetchPage') {
79+
await this.emit('data', messages.newMessageWithBody({ results: pageResults }));
80+
} else if (emitBehavior === 'emitIndividually') {
81+
for (const record of pageResults) {
82+
await this.emit('data', messages.newMessageWithBody(record));
83+
}
84+
}
8285

83-
if (singlePagePerInterval) {
86+
if (singlePagePerInterval) {
87+
await this.emit('snapshot', { nextStartTime: lastElementLastModifiedDate, lastElementId });
88+
proceed = false;
89+
}
90+
} else {
91+
hasNextPage = false;
92+
if (emitBehavior === 'fetchPage') {
93+
await this.emit('data', messages.newMessageWithBody({ results }));
94+
} else if (emitBehavior === 'emitIndividually') {
95+
for (const record of results) {
96+
await this.emit('data', messages.newMessageWithBody(record));
97+
}
98+
}
8499
await this.emit('snapshot', { nextStartTime });
85100
proceed = false;
86101
}

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"dotenv": "8.2.0",
3232
"elasticio-node": "0.0.9",
3333
"elasticio-rest-node": "1.2.7",
34-
"elasticio-sailor-nodejs": "2.6.29",
34+
"elasticio-sailor-nodejs": "2.7.0",
3535
"jsforce": "1.10.0",
3636
"mime-types": "2.1.27",
3737
"nyc": "15.1.0",

spec-integration/triggers/polling.spec.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
11
/* eslint-disable no-return-assign */
22
const { expect } = require('chai');
3-
const polling = require('../../lib/entry');
3+
const polling = require('../../lib/triggers/getUpdatedObjectsPolling');
44
const { getContext, testsCommon } = require('../../spec/common');
5+
const enrtyMetaModel = require('../../spec/triggers/outMetadataSchemas/entryObjectTypes.json');
56

67
const { getOauth } = testsCommon;
78

89
describe('polling', () => {
910
it('Account polling with empty snapshot', async () => {
10-
const testCfg = { oauth: getOauth(), sobject: 'Contact' };
11+
const testCfg = {
12+
oauth: getOauth(),
13+
sobject: 'Contact',
14+
emitBehavior: 'fetchPage',
15+
pageSize: 500,
16+
singlePagePerInterval: true,
17+
};
18+
const snapshot = {
19+
lastElementId: '0032R00002La0YtQAJ',
20+
};
1121
const msg = { body: {} };
12-
13-
await polling.process.call(getContext(), msg, testCfg, {});
22+
const context = getContext();
23+
await polling.process.call(context, msg, testCfg, snapshot);
24+
expect(context).to.deep.equal(enrtyMetaModel);
1425
});
1526

1627
it('Account polling with not empty snapshot', async () => {
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
[
2+
{
3+
"Id": "0034400001uxwXZAAY",
4+
"LastModifiedDate": "2021-04-19T04:35:12.000+0000",
5+
"name": 1
6+
},
7+
{
8+
"Id": "0034400001uxXuyAAE",
9+
"LastModifiedDate": "2021-11-29T16:51:59.000+0000",
10+
"name": 2
11+
},
12+
{
13+
"Id": "00344000020qT3KAAU",
14+
"LastModifiedDate": "2022-06-10T10:23:15.000+0000",
15+
"name": 3
16+
},
17+
{
18+
"Id": "0032R00002La0YtQAJ",
19+
"LastModifiedDate": "2022-07-05T09:14:53.000+0000",
20+
"name": 4
21+
},
22+
{
23+
"Id": "0032R00002La0ZXQAZ",
24+
"LastModifiedDate": "2022-07-05T09:25:14.000+0000",
25+
"name": 5
26+
},
27+
{
28+
"Id": "0032R00002La0ZcQAJ",
29+
"LastModifiedDate": "2022-07-05T09:25:14.000+0000",
30+
"name": 6
31+
},
32+
{
33+
"Id": "0032R00002La0ZhQAJ",
34+
"LastModifiedDate": "2022-07-05T09:25:15.000+0000",
35+
"name": 7
36+
},
37+
{
38+
"Id": "0032R00002La0ZrQAJ",
39+
"LastModifiedDate": "2022-07-05T09:28:36.000+0000",
40+
"name": 8
41+
},
42+
{
43+
"Id": "0032R00002La0a1QAB",
44+
"LastModifiedDate": "2022-07-05T09:28:37.000+0000",
45+
"name": 9
46+
},
47+
{
48+
"Id": "0032R00002La0aaQAB",
49+
"LastModifiedDate": "2022-07-05T09:28:37.000+0000",
50+
"name": 10
51+
},
52+
{
53+
"Id": "0032R00002La0apQAB",
54+
"LastModifiedDate": "2022-07-05T09:28:37.000+0000",
55+
"name": 11
56+
},
57+
{
58+
"Id": "0032R00002La0bxQAB",
59+
"LastModifiedDate": "2022-07-05T09:28:37.000+0000",
60+
"name": 12
61+
},
62+
{
63+
"Id": "0032R00002La0dFQAR",
64+
"LastModifiedDate": "2022-07-05T10:05:56.000+0000",
65+
"name": 13
66+
},
67+
{
68+
"Id": "0032R00002La0doQAB",
69+
"LastModifiedDate": "2022-07-05T10:09:05.000+0000",
70+
"name": 14
71+
},
72+
{
73+
"Id": "0032R00002La0dyQAB",
74+
"LastModifiedDate": "2022-07-05T10:09:06.000+0000",
75+
"name": 15
76+
},
77+
{
78+
"Id": "0032R00002La0ffQAB",
79+
"LastModifiedDate": "2022-07-05T10:25:03.000+0000",
80+
"name": 16
81+
},
82+
{
83+
"Id": "0032R00002La0fkQAB",
84+
"LastModifiedDate": "2022-07-05T10:25:04.000+0000",
85+
"name": 17
86+
},
87+
{
88+
"Id": "0032R00002La0fpQAB",
89+
"LastModifiedDate": "2022-07-05T10:25:05.000+0000",
90+
"name": 18
91+
},
92+
{
93+
"Id": "0032R00002La0gxQAB",
94+
"LastModifiedDate": "2022-07-05T10:38:35.000+0000",
95+
"name": 19
96+
},
97+
{
98+
"Id": "0032R00002La0h2QAB",
99+
"LastModifiedDate": "2022-07-05T10:44:45.000+0000",
100+
"name": 20
101+
},
102+
{
103+
"Id": "0032R00002La0hCQAR",
104+
"LastModifiedDate": "2022-07-05T10:44:45.000+0000",
105+
"name": 21
106+
},
107+
{
108+
"Id": "0032R00002La0hHQAR",
109+
"LastModifiedDate": "2022-07-05T10:44:46.000+0000",
110+
"name": 22
111+
},
112+
{
113+
"Id": "0032R00002La0hgQAB",
114+
"LastModifiedDate": "2022-07-05T10:54:18.000+0000",
115+
"name": 23
116+
},
117+
{
118+
"Id": "0032R00002La0hqQAB",
119+
"LastModifiedDate": "2022-07-05T10:54:19.000+0000",
120+
"name": 24
121+
},
122+
{
123+
"Id": "0032R00002La0itQAB",
124+
"LastModifiedDate": "2022-07-05T11:05:29.000+0000",
125+
"name": 25
126+
},
127+
{
128+
"Id": "0032R00002La0j3QAB",
129+
"LastModifiedDate": "2022-07-05T11:05:30.000+0000",
130+
"name": 26
131+
},
132+
{
133+
"Id": "0032R00002La0iyQAB",
134+
"LastModifiedDate": "2022-07-05T11:05:30.000+0000",
135+
"name": 27
136+
}
137+
]

0 commit comments

Comments
 (0)