@plusscommunities/pluss-core-aws 2.0.25-beta.6 → 2.0.25-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/helper/hqPublishing.js +28 -25
- package/package.json +1 -1
package/helper/hqPublishing.js
CHANGED
|
@@ -145,14 +145,23 @@ const fanOutHqSource = async (hqSourceRow, tableName) => {
|
|
|
145
145
|
return [];
|
|
146
146
|
}
|
|
147
147
|
const copyId = `hqcopy-${hqSourceRow.Id}`;
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
//
|
|
151
|
-
//
|
|
152
|
-
//
|
|
153
|
-
//
|
|
154
|
-
// the
|
|
148
|
+
// Preserve the HQ-source row's own UnixTimestamp on each copy rather than
|
|
149
|
+
// stamping "now". For an immediate publish the source timestamp already IS
|
|
150
|
+
// ~now, so feed ranking is unchanged; for a SCHEDULED publish (future
|
|
151
|
+
// timestamp set via the compose "Schedule Post" tab) preserving it keeps the
|
|
152
|
+
// copies hidden until the scheduled moment — BOTH consumers key off it: the
|
|
153
|
+
// noFuture feed filter, and the deferred-notification scheduler
|
|
154
|
+
// (watchNewsletter / the INSERT-path checkSendNotifications both gate on
|
|
155
|
+
// `UnixTimestamp < now`). Stamping "now" here published scheduled HQ posts
|
|
156
|
+
// (feed + push) immediately, ignoring the schedule. Fall back to now only if
|
|
157
|
+
// the source somehow lacks a timestamp.
|
|
158
|
+
//
|
|
159
|
+
// IMPORTANT: milliseconds (.valueOf), not seconds (.unix) — parity with the
|
|
160
|
+
// addNewsletterEntry UnixTimestamp convention. UnixTimestampReverse-keyed
|
|
161
|
+
// feed queries would otherwise mis-rank an ms value against a seconds value
|
|
162
|
+
// (MAX_SAFE_INTEGER minus 10^9 vs minus 10^12).
|
|
155
163
|
const now = moment.utc().valueOf();
|
|
164
|
+
const publishTs = hqSourceRow.UnixTimestamp || now;
|
|
156
165
|
|
|
157
166
|
const writes = targets.map((targetSiteId) => {
|
|
158
167
|
// Spread + override pattern: keep all content fields, swap identity
|
|
@@ -164,8 +173,8 @@ const fanOutHqSource = async (hqSourceRow, tableName) => {
|
|
|
164
173
|
copy.Site = targetSiteId;
|
|
165
174
|
copy.RowId = `${targetSiteId}_${copyId}`;
|
|
166
175
|
copy.HqSourceId = hqSourceRow.Id;
|
|
167
|
-
copy.UnixTimestamp =
|
|
168
|
-
copy.UnixTimestampReverse = Number.MAX_SAFE_INTEGER -
|
|
176
|
+
copy.UnixTimestamp = publishTs;
|
|
177
|
+
copy.UnixTimestampReverse = Number.MAX_SAFE_INTEGER - publishTs;
|
|
169
178
|
// Each copy's own INSERT fires publishNotifications via the existing
|
|
170
179
|
// pipeline. Setting UnsentNotification: "X" matches the convention
|
|
171
180
|
// used by addNewsletterEntry when caller requested a notification.
|
|
@@ -173,6 +182,11 @@ const fanOutHqSource = async (hqSourceRow, tableName) => {
|
|
|
173
182
|
// HQ-only fields don't travel:
|
|
174
183
|
delete copy.PublishedToSites;
|
|
175
184
|
delete copy.Deleted; // copies start undeleted; retract cascade is separate
|
|
185
|
+
// Tagged references HQ-site users; on a community copy those IDs are
|
|
186
|
+
// orphaned (cosmetic "tagged people" display + a createUserEntries write
|
|
187
|
+
// keyed on non-members in newsletterChanged's INSERT branch). Audience
|
|
188
|
+
// targeting (All/Category) already governs who sees the copy.
|
|
189
|
+
delete copy.Tagged;
|
|
176
190
|
return updateRef(tableName, copy).then(() => copy);
|
|
177
191
|
});
|
|
178
192
|
return Promise.all(writes);
|
|
@@ -312,8 +326,8 @@ const cascadeHqRetract = async (hqSourceRow, tableName, options = {}) => {
|
|
|
312
326
|
* @param {string} templateId — the `Id` of the contentLibrary row.
|
|
313
327
|
* @param {string} contentLibraryTable — entity-agnostic; caller passes the
|
|
314
328
|
* table name (without prefix).
|
|
315
|
-
* @returns {Promise<boolean>} `true` if increment applied; `false`
|
|
316
|
-
*
|
|
329
|
+
* @returns {Promise<boolean>} `true` if increment applied; `false` if table
|
|
330
|
+
* doesn't exist (graceful skip).
|
|
317
331
|
*/
|
|
318
332
|
const incrementTemplateUseCount = async (templateId, contentLibraryTable) => {
|
|
319
333
|
if (!templateId || !contentLibraryTable) {
|
|
@@ -322,16 +336,11 @@ const incrementTemplateUseCount = async (templateId, contentLibraryTable) => {
|
|
|
322
336
|
const params = {
|
|
323
337
|
TableName: `${process.env.tablePrefix}${contentLibraryTable}`,
|
|
324
338
|
Key: { Id: templateId },
|
|
325
|
-
UpdateExpression:
|
|
326
|
-
|
|
327
|
-
// it with UseCount=1. Only increment a template that actually exists; a
|
|
328
|
-
// stale/bogus TemplateId is skipped (ConditionalCheckFailed below).
|
|
329
|
-
ConditionExpression: "attribute_exists(Id)",
|
|
339
|
+
UpdateExpression:
|
|
340
|
+
"ADD UseCount :inc SET LastUsedTimestamp = :now",
|
|
330
341
|
ExpressionAttributeValues: {
|
|
331
342
|
":inc": 1,
|
|
332
|
-
|
|
333
|
-
// UpdatedAt). Was .unix() (seconds); reconciled to .valueOf().
|
|
334
|
-
":now": moment().utc().valueOf(),
|
|
343
|
+
":now": moment.utc().unix(),
|
|
335
344
|
},
|
|
336
345
|
};
|
|
337
346
|
try {
|
|
@@ -349,12 +358,6 @@ const incrementTemplateUseCount = async (templateId, contentLibraryTable) => {
|
|
|
349
358
|
);
|
|
350
359
|
return false;
|
|
351
360
|
}
|
|
352
|
-
if (error?.code === "ConditionalCheckFailedException") {
|
|
353
|
-
// TemplateId references no existing template — skip rather than
|
|
354
|
-
// create a phantom row. Not an error; continue the stream handler.
|
|
355
|
-
log("incrementTemplateUseCount", "NoSuchTemplate", { templateId });
|
|
356
|
-
return false;
|
|
357
|
-
}
|
|
358
361
|
// Anything else is genuinely unexpected — surface it.
|
|
359
362
|
log("incrementTemplateUseCount", "Error", error);
|
|
360
363
|
throw error;
|
package/package.json
CHANGED