@easy-cms/core 0.7.0 → 0.8.0

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/dist/index.d.ts CHANGED
@@ -1008,14 +1008,14 @@ declare class EasyCMS<C extends Config = Config> {
1008
1008
  };
1009
1009
  }>;
1010
1010
  /**
1011
- * Tries webhook deliveries that failed earlier and are due for another attempt. Failed
1012
- * deliveries are kept in the database, so they survive restarts.
1011
+ * Tries webhook deliveries that are due for another attempt. Deliveries are kept in the
1012
+ * database until they succeed, so they survive restarts.
1013
1013
  */
1014
1014
  retryWebhooks(now?: Date): Promise<{
1015
1015
  sent: number;
1016
1016
  failed: number;
1017
1017
  }>;
1018
- /** Failed webhook deliveries, stored in `webhook-deliveries`. */
1018
+ /** Webhook deliveries until they succeed, stored in `webhook-deliveries`. */
1019
1019
  private webhookQueue;
1020
1020
  /**
1021
1021
  * Publishes or unpublishes documents whose scheduled time has come. Safe to call often, e.g.
package/dist/index.js CHANGED
@@ -1044,6 +1044,8 @@ var Webhooks = class {
1044
1044
  fetcher;
1045
1045
  retryDelays;
1046
1046
  pending = /* @__PURE__ */ new Set();
1047
+ /** Deliveries are saved one after another, so they are first sent in the order of events. */
1048
+ saving = Promise.resolve();
1047
1049
  emit(event, target, doc) {
1048
1050
  if (this.hooks.length === 0) return;
1049
1051
  const payload = { event, ...target, doc, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
@@ -1079,7 +1081,7 @@ var Webhooks = class {
1079
1081
  sent++;
1080
1082
  continue;
1081
1083
  }
1082
- const delay = QUEUE_DELAYS[attempts - this.retryDelays.length - 1];
1084
+ const delay = QUEUE_DELAYS[Math.max(0, attempts - this.retryDelays.length - 1)];
1083
1085
  if (delay === void 0) failed++;
1084
1086
  await this.queue.update(id, {
1085
1087
  ...queued,
@@ -1100,37 +1102,43 @@ var Webhooks = class {
1100
1102
  const delivery = randomUUID2();
1101
1103
  const body = JSON.stringify(payload);
1102
1104
  const { event } = payload;
1105
+ const entry = (attempts, nextAttemptAt, error) => ({
1106
+ url: hook.url,
1107
+ event,
1108
+ body,
1109
+ delivery,
1110
+ attempts,
1111
+ nextAttemptAt,
1112
+ state: "pending",
1113
+ error
1114
+ });
1115
+ const { queue } = this;
1116
+ const saved = queue ? this.saving.then(() => queue.add(entry(0, later(/* @__PURE__ */ new Date(), CLAIM), null))) : Promise.resolve(void 0);
1117
+ this.saving = saved.catch(() => {
1118
+ });
1103
1119
  let queued;
1120
+ try {
1121
+ queued = await saved;
1122
+ } catch (error) {
1123
+ this.logger.error(`Could not save webhook delivery: ${error.message}`);
1124
+ }
1104
1125
  for (let attempt = 0; ; attempt++) {
1105
1126
  const result = await this.attempt(hook, event, body, delivery);
1106
1127
  if (result.ok) {
1107
1128
  if (queued !== void 0) await this.queue?.remove(queued);
1108
1129
  return;
1109
1130
  }
1110
- const entry = (nextAttemptAt) => ({
1111
- url: hook.url,
1112
- event,
1113
- body,
1114
- delivery,
1115
- attempts: attempt + 1,
1116
- nextAttemptAt,
1117
- state: "pending",
1118
- error: result.error
1119
- });
1120
1131
  const delay = this.retryDelays[attempt];
1121
1132
  if (delay === void 0) {
1122
- if (!this.queue) return this.giveUp(hook, event, result.error, attempt + 1);
1123
- const next = entry(later(/* @__PURE__ */ new Date(), QUEUE_DELAYS[0]));
1124
- if (queued === void 0) await this.queue.add(next);
1125
- else await this.queue.update(queued, next);
1133
+ if (queued === void 0 || !this.queue)
1134
+ return this.giveUp(hook, event, result.error, attempt + 1);
1135
+ const next = later(/* @__PURE__ */ new Date(), QUEUE_DELAYS[0]);
1136
+ await this.queue.update(queued, entry(attempt + 1, next, result.error));
1126
1137
  this.logger.warn(
1127
1138
  `Webhook ${hook.url} failed for ${event} (${result.error}); will retry later`
1128
1139
  );
1129
1140
  return;
1130
1141
  }
1131
- if (this.queue && queued === void 0) {
1132
- queued = await this.queue.add(entry(later(/* @__PURE__ */ new Date(), CLAIM)));
1133
- }
1134
1142
  await new Promise((resolve3) => setTimeout(resolve3, delay));
1135
1143
  }
1136
1144
  }
@@ -2870,13 +2878,13 @@ var EasyCMS = class {
2870
2878
  return { ...scheduled, webhooks: await this.retryWebhooks(now) };
2871
2879
  }
2872
2880
  /**
2873
- * Tries webhook deliveries that failed earlier and are due for another attempt. Failed
2874
- * deliveries are kept in the database, so they survive restarts.
2881
+ * Tries webhook deliveries that are due for another attempt. Deliveries are kept in the
2882
+ * database until they succeed, so they survive restarts.
2875
2883
  */
2876
2884
  retryWebhooks(now = /* @__PURE__ */ new Date()) {
2877
2885
  return this.webhooks.retry(now);
2878
2886
  }
2879
- /** Failed webhook deliveries, stored in `webhook-deliveries`. */
2887
+ /** Webhook deliveries until they succeed, stored in `webhook-deliveries`. */
2880
2888
  webhookQueue() {
2881
2889
  const collection2 = WEBHOOK_DELIVERIES;
2882
2890
  const toRow = (d, createdAt) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easy-cms/core",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Embedded, code-first headless CMS for Nuxt and Next.js",
5
5
  "license": "MIT",
6
6
  "type": "module",