@nextage/era-lib 1.0.197 → 1.0.199
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/build/events/base/base-event.controller.d.ts +49 -5
- package/build/events/base/base-event.controller.d.ts.map +1 -1
- package/build/events/base/base-event.controller.js +65 -6
- package/build/events/base/base-event.controller.js.map +1 -1
- package/build/events/types/enums.d.ts +12 -1
- package/build/events/types/enums.d.ts.map +1 -1
- package/build/events/types/enums.js +11 -0
- package/build/events/types/enums.js.map +1 -1
- package/build/services/tenant-archive.d.ts +30 -10
- package/build/services/tenant-archive.d.ts.map +1 -1
- package/build/services/tenant-archive.interfaces.d.ts +13 -1
- package/build/services/tenant-archive.interfaces.d.ts.map +1 -1
- package/build/services/tenant-archive.js +103 -17
- package/build/services/tenant-archive.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ import { BaseController } from '@nextage/nx-frame-be/build/common/base/base.cont
|
|
|
4
4
|
import { NxContext } from '@nextage/nx-frame-be';
|
|
5
5
|
import { Event, IPublisher } from '../interfaces';
|
|
6
6
|
import { PublisherProvider } from '../types/relay.interfaces';
|
|
7
|
-
import { QueueEventType } from '../types/enums';
|
|
7
|
+
import { QueueEventType, Subjects } from '../types/enums';
|
|
8
8
|
export declare abstract class BaseEventCtrl<TCreate extends Event, TUpdate extends Event, TRemove extends Event, TAttrs, TDoc extends BaseMongoDoc, TModel extends BaseModel<TAttrs, TDoc, any>> extends BaseController<TAttrs, TDoc, TModel> implements PublisherProvider {
|
|
9
9
|
/**
|
|
10
10
|
* Declarative publish field-map (Step 3.4c). The default parsePub* methods pick
|
|
@@ -29,16 +29,39 @@ export declare abstract class BaseEventCtrl<TCreate extends Event, TUpdate exten
|
|
|
29
29
|
protected abstract createPublisher: IPublisher<TCreate>[];
|
|
30
30
|
protected abstract updatePublisher: IPublisher<TUpdate>[];
|
|
31
31
|
protected abstract removePublisher: IPublisher<TRemove>[];
|
|
32
|
+
/**
|
|
33
|
+
* Publishers for the project events that do NOT originate from a create/update/
|
|
34
|
+
* remove (e.g. `organization.restored`, emitted by a restore mutation). Empty by
|
|
35
|
+
* default, so none of the existing controllers changes behaviour.
|
|
36
|
+
*
|
|
37
|
+
* Declaring them HERE, instead of keeping them private to the subclass, is what
|
|
38
|
+
* makes the relay's invariant structural: `eventPublishers()` exposes them to the
|
|
39
|
+
* registry, so an outbox row left at `sent:false` is found again BY SUBJECT and
|
|
40
|
+
* republished. A custom publisher declared anywhere else would produce rows the
|
|
41
|
+
* relay skips on every pass, forever: never lost, never delivered.
|
|
42
|
+
*/
|
|
43
|
+
protected customPublishers: IPublisher<Event>[];
|
|
32
44
|
constructor(config: {
|
|
33
45
|
model: TModel;
|
|
34
46
|
mergeUpdate?: boolean;
|
|
35
47
|
});
|
|
36
48
|
/**
|
|
37
|
-
* All publishers this controller owns (create + update + remove). Read
|
|
38
|
-
* the relay's publisher registry to route a `sent:false` outbox row back
|
|
39
|
-
* publisher family by subject
|
|
49
|
+
* All publishers this controller owns (create + update + remove + custom). Read
|
|
50
|
+
* LAZILY by the relay's publisher registry to route a `sent:false` outbox row back
|
|
51
|
+
* to its publisher family by subject - so it runs after the subclass field
|
|
52
|
+
* initializers. The custom ones belong here too: they are outbox rows like any
|
|
53
|
+
* other, and without them the relay could not trace those rows back to a publisher.
|
|
40
54
|
*/
|
|
41
55
|
eventPublishers(): IPublisher<Event>[];
|
|
56
|
+
/**
|
|
57
|
+
* The custom publishers declared for a subject. The subject is also the relay's
|
|
58
|
+
* routing key (`resolvePublishers(row.subject)`), so resolving locally by the very
|
|
59
|
+
* same criterion keeps what is published now and what would be republished after a
|
|
60
|
+
* failure one and the same thing.
|
|
61
|
+
*
|
|
62
|
+
* @param subject
|
|
63
|
+
*/
|
|
64
|
+
private customPublishersFor;
|
|
42
65
|
private publishConfig?;
|
|
43
66
|
/**
|
|
44
67
|
* Inizializza la configurazione dei publisher (lazy initialization)
|
|
@@ -64,11 +87,32 @@ export declare abstract class BaseEventCtrl<TCreate extends Event, TUpdate exten
|
|
|
64
87
|
private buildMessage;
|
|
65
88
|
/**
|
|
66
89
|
* Dispatch a prepared message on every publisher of its type. Shared by the
|
|
67
|
-
* immediate post-commit dispatch and the relay replay.
|
|
90
|
+
* immediate post-commit dispatch and the relay replay. A custom message has no
|
|
91
|
+
* publisher family tied to its type: it is resolved by subject.
|
|
68
92
|
*
|
|
69
93
|
* @param msg
|
|
70
94
|
*/
|
|
71
95
|
private publishMessage;
|
|
96
|
+
/**
|
|
97
|
+
* Emit a project event that does not originate from an entity write (e.g.
|
|
98
|
+
* `organization.restored`), with the same guarantee as every other one: outbox row
|
|
99
|
+
* first, publish next, `sent:true` only once it has been delivered. A broker
|
|
100
|
+
* failure leaves a row the relay can recover, never a lost event.
|
|
101
|
+
*
|
|
102
|
+
* Fails when the subject has no publisher among `customPublishers`: without one we
|
|
103
|
+
* would write a row nobody could ever republish. Better not to emit at all than to
|
|
104
|
+
* emit something unrecoverable.
|
|
105
|
+
*
|
|
106
|
+
* WARNING: unlike create/update/remove there is NO transaction tying the outbox row
|
|
107
|
+
* to the write - the caller decides where to place the call. It belongs AFTER the
|
|
108
|
+
* operation succeeded: of the two ways to get this wrong, an event missing on a
|
|
109
|
+
* successful operation can be repaired, an event emitted on a failed one cannot.
|
|
110
|
+
*
|
|
111
|
+
* @param subject
|
|
112
|
+
* @param data
|
|
113
|
+
* @param context
|
|
114
|
+
*/
|
|
115
|
+
protected publishCustomEvent(subject: Subjects, data: any, context: NxContext): Promise<void>;
|
|
72
116
|
/**
|
|
73
117
|
* Overridable post-write / post-read enrichment of the RETURNED document (e.g.
|
|
74
118
|
* populate references, attach a joined aggregate). Runs AFTER the atomic write
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-event.controller.d.ts","sourceRoot":"","sources":["../../../src/events/base/base-event.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAuB,mDAAmD,CAAC;AAC/F,OAAO,EAAE,YAAY,EAAE,MAAoB,wDAAwD,CAAC;AACpG,OAAO,EAAE,cAAc,EAAE,MAAkB,wDAAwD,CAAC;AAEpG,OAAO,EAAE,SAAS,EAAE,MAAuB,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"base-event.controller.d.ts","sourceRoot":"","sources":["../../../src/events/base/base-event.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -42,15 +42,40 @@ class BaseEventCtrl extends base_controller_1.BaseController {
|
|
|
42
42
|
*/
|
|
43
43
|
this.pubFields = [];
|
|
44
44
|
this.pubRemoveFields = [];
|
|
45
|
+
/**
|
|
46
|
+
* Publishers for the project events that do NOT originate from a create/update/
|
|
47
|
+
* remove (e.g. `organization.restored`, emitted by a restore mutation). Empty by
|
|
48
|
+
* default, so none of the existing controllers changes behaviour.
|
|
49
|
+
*
|
|
50
|
+
* Declaring them HERE, instead of keeping them private to the subclass, is what
|
|
51
|
+
* makes the relay's invariant structural: `eventPublishers()` exposes them to the
|
|
52
|
+
* registry, so an outbox row left at `sent:false` is found again BY SUBJECT and
|
|
53
|
+
* republished. A custom publisher declared anywhere else would produce rows the
|
|
54
|
+
* relay skips on every pass, forever: never lost, never delivered.
|
|
55
|
+
*/
|
|
56
|
+
this.customPublishers = [];
|
|
45
57
|
(0, publisher_registry_1.registerPublisherProvider)(this);
|
|
46
58
|
}
|
|
47
59
|
/**
|
|
48
|
-
* All publishers this controller owns (create + update + remove). Read
|
|
49
|
-
* the relay's publisher registry to route a `sent:false` outbox row back
|
|
50
|
-
* publisher family by subject
|
|
60
|
+
* All publishers this controller owns (create + update + remove + custom). Read
|
|
61
|
+
* LAZILY by the relay's publisher registry to route a `sent:false` outbox row back
|
|
62
|
+
* to its publisher family by subject - so it runs after the subclass field
|
|
63
|
+
* initializers. The custom ones belong here too: they are outbox rows like any
|
|
64
|
+
* other, and without them the relay could not trace those rows back to a publisher.
|
|
51
65
|
*/
|
|
52
66
|
eventPublishers() {
|
|
53
|
-
return [...this.createPublisher, ...this.updatePublisher, ...this.removePublisher];
|
|
67
|
+
return [...this.createPublisher, ...this.updatePublisher, ...this.removePublisher, ...this.customPublishers];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The custom publishers declared for a subject. The subject is also the relay's
|
|
71
|
+
* routing key (`resolvePublishers(row.subject)`), so resolving locally by the very
|
|
72
|
+
* same criterion keeps what is published now and what would be republished after a
|
|
73
|
+
* failure one and the same thing.
|
|
74
|
+
*
|
|
75
|
+
* @param subject
|
|
76
|
+
*/
|
|
77
|
+
customPublishersFor(subject) {
|
|
78
|
+
return this.customPublishers.filter(pub => pub.subject === subject);
|
|
54
79
|
}
|
|
55
80
|
/**
|
|
56
81
|
* Inizializza la configurazione dei publisher (lazy initialization)
|
|
@@ -120,14 +145,48 @@ class BaseEventCtrl extends base_controller_1.BaseController {
|
|
|
120
145
|
}
|
|
121
146
|
/**
|
|
122
147
|
* Dispatch a prepared message on every publisher of its type. Shared by the
|
|
123
|
-
* immediate post-commit dispatch and the relay replay.
|
|
148
|
+
* immediate post-commit dispatch and the relay replay. A custom message has no
|
|
149
|
+
* publisher family tied to its type: it is resolved by subject.
|
|
124
150
|
*
|
|
125
151
|
* @param msg
|
|
126
152
|
*/
|
|
127
153
|
async publishMessage(msg) {
|
|
128
|
-
const publishers =
|
|
154
|
+
const publishers = msg.type === enums_1.QueueEventType.custom
|
|
155
|
+
? this.customPublishersFor(msg.subject)
|
|
156
|
+
: this.getPublishConfig()[msg.type]?.publishers ?? [];
|
|
129
157
|
await Promise.all(publishers.map(pub => pub.publish(msg.data, msg.meta)));
|
|
130
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Emit a project event that does not originate from an entity write (e.g.
|
|
161
|
+
* `organization.restored`), with the same guarantee as every other one: outbox row
|
|
162
|
+
* first, publish next, `sent:true` only once it has been delivered. A broker
|
|
163
|
+
* failure leaves a row the relay can recover, never a lost event.
|
|
164
|
+
*
|
|
165
|
+
* Fails when the subject has no publisher among `customPublishers`: without one we
|
|
166
|
+
* would write a row nobody could ever republish. Better not to emit at all than to
|
|
167
|
+
* emit something unrecoverable.
|
|
168
|
+
*
|
|
169
|
+
* WARNING: unlike create/update/remove there is NO transaction tying the outbox row
|
|
170
|
+
* to the write - the caller decides where to place the call. It belongs AFTER the
|
|
171
|
+
* operation succeeded: of the two ways to get this wrong, an event missing on a
|
|
172
|
+
* successful operation can be repaired, an event emitted on a failed one cannot.
|
|
173
|
+
*
|
|
174
|
+
* @param subject
|
|
175
|
+
* @param data
|
|
176
|
+
* @param context
|
|
177
|
+
*/
|
|
178
|
+
async publishCustomEvent(subject, data, context) {
|
|
179
|
+
if (!this.customPublishersFor(subject).length)
|
|
180
|
+
throw new Error(`[BaseEventCtrl] no publisher declared in 'customPublishers' for subject '${subject}'`);
|
|
181
|
+
const msg = {
|
|
182
|
+
type: enums_1.QueueEventType.custom,
|
|
183
|
+
subject,
|
|
184
|
+
data,
|
|
185
|
+
meta: (0, cascade_1.outgoingMeta)(context?._event),
|
|
186
|
+
};
|
|
187
|
+
const outboxId = await this.enqueueOutbox(msg, context);
|
|
188
|
+
await this.dispatchOutbox(msg, outboxId, context);
|
|
189
|
+
}
|
|
131
190
|
/**
|
|
132
191
|
* Overridable post-write / post-read enrichment of the RETURNED document (e.g.
|
|
133
192
|
* populate references, attach a joined aggregate). Runs AFTER the atomic write
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-event.controller.js","sourceRoot":"","sources":["../../../src/events/base/base-event.controller.ts"],"names":[],"mappings":";;;AAEA,4FAAoG;AACpG,oFAAgG;
|
|
1
|
+
{"version":3,"file":"base-event.controller.js","sourceRoot":"","sources":["../../../src/events/base/base-event.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -92,6 +92,17 @@ export declare enum Subjects {
|
|
|
92
92
|
export declare enum QueueEventType {
|
|
93
93
|
create = "queue.create",
|
|
94
94
|
update = "queue.update",
|
|
95
|
-
remove = "queue.remove"
|
|
95
|
+
remove = "queue.remove",
|
|
96
|
+
/**
|
|
97
|
+
* An event a controller publishes on its own, outside the CRUD trio.
|
|
98
|
+
*
|
|
99
|
+
* Not every meaningful thing that happens to an entity is a create, an update
|
|
100
|
+
* or a remove: `organization.restored` (T42) is the first, and it comes from a
|
|
101
|
+
* cascade that touches several collections and matches none of the three. Such
|
|
102
|
+
* events still belong on the outbox - the guarantee is the point, not the verb -
|
|
103
|
+
* so they get a type of their own rather than being squeezed into `update`,
|
|
104
|
+
* where they would inherit the `parsePub*` field-map and lie about what happened.
|
|
105
|
+
*/
|
|
106
|
+
custom = "queue.custom"
|
|
96
107
|
}
|
|
97
108
|
//# sourceMappingURL=enums.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enums.d.ts","sourceRoot":"","sources":["../../../src/events/types/enums.ts"],"names":[],"mappings":"AAAA,oBAAY,QAAQ;IAElB;;sBAEkB;IAGlB,mBAAmB,yBAA8B;IACjD,mBAAmB,yBAA8B;IACjD,mBAAmB,yBAA8B;IAGjD,eAAe,qBAA8B;IAC7C,eAAe,qBAA8B;IAC7C,eAAe,qBAA8B;IAG7C,oBAAoB,0BAA8B;IAClD,oBAAoB,0BAA8B;IAClD,oBAAoB,0BAA8B;IAGlD,kBAAkB,wBAA8B;IAChD,kBAAkB,wBAA8B;IAChD,kBAAkB,wBAA8B;IAGhD,uBAAuB,6BAA8B;IACrD,uBAAuB,6BAA8B;IACrD,uBAAuB,6BAA8B;IAGrD,gBAAgB,sBAA8B;IAC9C,gBAAgB,sBAA8B;IAC9C,gBAAgB,sBAA8B;IAE9C;;sBAEkB;IAGlB,iBAAiB,uBAA2B;IAC5C,iBAAiB,uBAA2B;IAC5C,iBAAiB,uBAA2B;IAG5C,cAAc,oBAA2B;IACzC,cAAc,oBAA2B;IACzC,cAAc,oBAA2B;IAGzC,aAAa,mBAA2B;IACxC,aAAa,mBAA2B;IACxC,aAAa,mBAA2B;IAGxC,oBAAoB,iBAAkB;IACtC,oBAAoB,iBAAkB;IACtC,oBAAoB,iBAAkB;IAEtC;;uBAEmB;IAGnB,WAAW,iBAA0B;IACrC,WAAW,iBAA0B;IACrC,WAAW,iBAA0B;IAGrC,mBAAmB,yBAA0B;IAC7C,mBAAmB,yBAA0B;IAC7C,mBAAmB,yBAA0B;IAG7C,oBAAoB,0BAA0B;IAE9C;;uBAEmB;IAGnB,cAAc,oBAA4B;IAC1C,cAAc,oBAA4B;IAC1C,cAAc,oBAA4B;IAG1C,mBAAmB,0BAA6B;IAChD,mBAAmB,0BAA6B;IAChD,mBAAmB,0BAA6B;IAGhD,qBAAqB,4BAA6B;IAClD,qBAAqB,4BAA6B;IAClD,qBAAqB,4BAA6B;IAGlD,oBAAoB,2BAA6B;IACjD,oBAAoB,2BAA6B;IACjD,oBAAoB,2BAA6B;IAGjD,sBAAsB,6BAA6B;IACnD,sBAAsB,6BAA6B;IACnD,sBAAsB,6BAA6B;IAGnD,kBAAkB,yBAA6B;IAC/C,kBAAkB,yBAA6B;IAC/C,kBAAkB,yBAA6B;IAG/C,sBAAsB,6BAA6B;IACnD,sBAAsB,6BAA6B;IACnD,sBAAsB,6BAA6B;IAGnD,qBAAqB,4BAA6B;IAClD,qBAAqB,4BAA6B;IAClD,qBAAqB,4BAA6B;IAElD;;sBAEkB;IAGlB,mBAAmB,0BAA0B;IAC7C,mBAAmB,0BAA0B;IAC7C,mBAAmB,0BAA0B;IAG7C,gBAAgB,uBAA0B;IAC1C,gBAAgB,uBAA0B;IAC1C,gBAAgB,uBAA0B;IAE1C;;sBAEkB;IAOlB;;sBAEkB;IAKlB,aAAa,mBAAyB;CACvC;AAED,oBAAY,cAAc;IACxB,MAAM,iBAAiB;IACvB,MAAM,iBAAiB;IACvB,MAAM,iBAAiB;CACxB"}
|
|
1
|
+
{"version":3,"file":"enums.d.ts","sourceRoot":"","sources":["../../../src/events/types/enums.ts"],"names":[],"mappings":"AAAA,oBAAY,QAAQ;IAElB;;sBAEkB;IAGlB,mBAAmB,yBAA8B;IACjD,mBAAmB,yBAA8B;IACjD,mBAAmB,yBAA8B;IAGjD,eAAe,qBAA8B;IAC7C,eAAe,qBAA8B;IAC7C,eAAe,qBAA8B;IAG7C,oBAAoB,0BAA8B;IAClD,oBAAoB,0BAA8B;IAClD,oBAAoB,0BAA8B;IAGlD,kBAAkB,wBAA8B;IAChD,kBAAkB,wBAA8B;IAChD,kBAAkB,wBAA8B;IAGhD,uBAAuB,6BAA8B;IACrD,uBAAuB,6BAA8B;IACrD,uBAAuB,6BAA8B;IAGrD,gBAAgB,sBAA8B;IAC9C,gBAAgB,sBAA8B;IAC9C,gBAAgB,sBAA8B;IAE9C;;sBAEkB;IAGlB,iBAAiB,uBAA2B;IAC5C,iBAAiB,uBAA2B;IAC5C,iBAAiB,uBAA2B;IAG5C,cAAc,oBAA2B;IACzC,cAAc,oBAA2B;IACzC,cAAc,oBAA2B;IAGzC,aAAa,mBAA2B;IACxC,aAAa,mBAA2B;IACxC,aAAa,mBAA2B;IAGxC,oBAAoB,iBAAkB;IACtC,oBAAoB,iBAAkB;IACtC,oBAAoB,iBAAkB;IAEtC;;uBAEmB;IAGnB,WAAW,iBAA0B;IACrC,WAAW,iBAA0B;IACrC,WAAW,iBAA0B;IAGrC,mBAAmB,yBAA0B;IAC7C,mBAAmB,yBAA0B;IAC7C,mBAAmB,yBAA0B;IAG7C,oBAAoB,0BAA0B;IAE9C;;uBAEmB;IAGnB,cAAc,oBAA4B;IAC1C,cAAc,oBAA4B;IAC1C,cAAc,oBAA4B;IAG1C,mBAAmB,0BAA6B;IAChD,mBAAmB,0BAA6B;IAChD,mBAAmB,0BAA6B;IAGhD,qBAAqB,4BAA6B;IAClD,qBAAqB,4BAA6B;IAClD,qBAAqB,4BAA6B;IAGlD,oBAAoB,2BAA6B;IACjD,oBAAoB,2BAA6B;IACjD,oBAAoB,2BAA6B;IAGjD,sBAAsB,6BAA6B;IACnD,sBAAsB,6BAA6B;IACnD,sBAAsB,6BAA6B;IAGnD,kBAAkB,yBAA6B;IAC/C,kBAAkB,yBAA6B;IAC/C,kBAAkB,yBAA6B;IAG/C,sBAAsB,6BAA6B;IACnD,sBAAsB,6BAA6B;IACnD,sBAAsB,6BAA6B;IAGnD,qBAAqB,4BAA6B;IAClD,qBAAqB,4BAA6B;IAClD,qBAAqB,4BAA6B;IAElD;;sBAEkB;IAGlB,mBAAmB,0BAA0B;IAC7C,mBAAmB,0BAA0B;IAC7C,mBAAmB,0BAA0B;IAG7C,gBAAgB,uBAA0B;IAC1C,gBAAgB,uBAA0B;IAC1C,gBAAgB,uBAA0B;IAE1C;;sBAEkB;IAOlB;;sBAEkB;IAKlB,aAAa,mBAAyB;CACvC;AAED,oBAAY,cAAc;IACxB,MAAM,iBAAiB;IACvB,MAAM,iBAAiB;IACvB,MAAM,iBAAiB;IAEvB;;;;;;;;;OASG;IACH,MAAM,iBAAiB;CACxB"}
|
|
@@ -129,5 +129,16 @@ var QueueEventType;
|
|
|
129
129
|
QueueEventType["create"] = "queue.create";
|
|
130
130
|
QueueEventType["update"] = "queue.update";
|
|
131
131
|
QueueEventType["remove"] = "queue.remove";
|
|
132
|
+
/**
|
|
133
|
+
* An event a controller publishes on its own, outside the CRUD trio.
|
|
134
|
+
*
|
|
135
|
+
* Not every meaningful thing that happens to an entity is a create, an update
|
|
136
|
+
* or a remove: `organization.restored` (T42) is the first, and it comes from a
|
|
137
|
+
* cascade that touches several collections and matches none of the three. Such
|
|
138
|
+
* events still belong on the outbox - the guarantee is the point, not the verb -
|
|
139
|
+
* so they get a type of their own rather than being squeezed into `update`,
|
|
140
|
+
* where they would inherit the `parsePub*` field-map and lie about what happened.
|
|
141
|
+
*/
|
|
142
|
+
QueueEventType["custom"] = "queue.custom";
|
|
132
143
|
})(QueueEventType || (exports.QueueEventType = QueueEventType = {}));
|
|
133
144
|
//# sourceMappingURL=enums.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enums.js","sourceRoot":"","sources":["../../../src/events/types/enums.ts"],"names":[],"mappings":";;;AAAA,IAAY,QAwJX;AAxJD,WAAY,QAAQ;IAElB;;sBAEkB;IAElB,gBAAgB;IAChB,wDAAiD,CAAA;IACjD,wDAAiD,CAAA;IACjD,wDAAiD,CAAA;IAEjD,WAAW;IACX,gDAA6C,CAAA;IAC7C,gDAA6C,CAAA;IAC7C,gDAA6C,CAAA;IAE7C,gBAAgB;IAChB,0DAAkD,CAAA;IAClD,0DAAkD,CAAA;IAClD,0DAAkD,CAAA;IAElD,cAAc;IACd,sDAAgD,CAAA;IAChD,sDAAgD,CAAA;IAChD,sDAAgD,CAAA;IAEhD,mBAAmB;IACnB,gEAAqD,CAAA;IACrD,gEAAqD,CAAA;IACrD,gEAAqD,CAAA;IAErD,YAAY;IACZ,kDAA8C,CAAA;IAC9C,kDAA8C,CAAA;IAC9C,kDAA8C,CAAA;IAE9C;;sBAEkB;IAElB,cAAc;IACd,oDAA4C,CAAA;IAC5C,oDAA4C,CAAA;IAC5C,oDAA4C,CAAA;IAE5C,UAAU;IACV,8CAAyC,CAAA;IACzC,8CAAyC,CAAA;IACzC,8CAAyC,CAAA;IAEzC,SAAS;IACT,4CAAwC,CAAA;IACxC,4CAAwC,CAAA;IACxC,4CAAwC,CAAA;IAExC,gBAAgB;IAChB,iDAAsC,CAAA;IACtC,iDAAsC,CAAA;IACtC,iDAAsC,CAAA;IAEtC;;uBAEmB;IAEnB,OAAO;IACP,wCAAqC,CAAA;IACrC,wCAAqC,CAAA;IACrC,wCAAqC,CAAA;IAErC,eAAe;IACf,wDAA6C,CAAA;IAC7C,wDAA6C,CAAA;IAC7C,wDAA6C,CAAA;IAC7C,+EAA+E;IAC/E,oEAAoE;IACpE,0DAA8C,CAAA;IAE9C;;uBAEmB;IAEnB,UAAU;IACV,8CAA0C,CAAA;IAC1C,8CAA0C,CAAA;IAC1C,8CAA0C,CAAA;IAE1C,kBAAkB;IAClB,yDAAgD,CAAA;IAChD,yDAAgD,CAAA;IAChD,yDAAgD,CAAA;IAEhD,iBAAiB;IACjB,6DAAkD,CAAA;IAClD,6DAAkD,CAAA;IAClD,6DAAkD,CAAA;IAElD,kBAAkB;IAClB,2DAAiD,CAAA;IACjD,2DAAiD,CAAA;IACjD,2DAAiD,CAAA;IAEjD,WAAW;IACX,+DAAmD,CAAA;IACnD,+DAAmD,CAAA;IACnD,+DAAmD,CAAA;IAEnD,eAAe;IACf,uDAA+C,CAAA;IAC/C,uDAA+C,CAAA;IAC/C,uDAA+C,CAAA;IAE/C,WAAW;IACX,+DAAmD,CAAA;IACnD,+DAAmD,CAAA;IACnD,+DAAmD,CAAA;IAEnD,UAAU;IACV,6DAAkD,CAAA;IAClD,6DAAkD,CAAA;IAClD,6DAAkD,CAAA;IAElD;;sBAEkB;IAElB,gBAAgB;IAChB,yDAA6C,CAAA;IAC7C,yDAA6C,CAAA;IAC7C,yDAA6C,CAAA;IAE7C,aAAa;IACb,mDAA0C,CAAA;IAC1C,mDAA0C,CAAA;IAC1C,mDAA0C,CAAA;IAE1C;;sBAEkB;IAElB,mBAAmB;IACnB,2CAA2C;IAC3C,2CAA2C;IAC3C,2CAA2C;IAE3C;;sBAEkB;IAElB,0EAA0E;IAC1E,uEAAuE;IACvE,yDAAyD;IACzD,4CAAsC,CAAA;AACxC,CAAC,EAxJW,QAAQ,wBAAR,QAAQ,QAwJnB;AAED,IAAY,
|
|
1
|
+
{"version":3,"file":"enums.js","sourceRoot":"","sources":["../../../src/events/types/enums.ts"],"names":[],"mappings":";;;AAAA,IAAY,QAwJX;AAxJD,WAAY,QAAQ;IAElB;;sBAEkB;IAElB,gBAAgB;IAChB,wDAAiD,CAAA;IACjD,wDAAiD,CAAA;IACjD,wDAAiD,CAAA;IAEjD,WAAW;IACX,gDAA6C,CAAA;IAC7C,gDAA6C,CAAA;IAC7C,gDAA6C,CAAA;IAE7C,gBAAgB;IAChB,0DAAkD,CAAA;IAClD,0DAAkD,CAAA;IAClD,0DAAkD,CAAA;IAElD,cAAc;IACd,sDAAgD,CAAA;IAChD,sDAAgD,CAAA;IAChD,sDAAgD,CAAA;IAEhD,mBAAmB;IACnB,gEAAqD,CAAA;IACrD,gEAAqD,CAAA;IACrD,gEAAqD,CAAA;IAErD,YAAY;IACZ,kDAA8C,CAAA;IAC9C,kDAA8C,CAAA;IAC9C,kDAA8C,CAAA;IAE9C;;sBAEkB;IAElB,cAAc;IACd,oDAA4C,CAAA;IAC5C,oDAA4C,CAAA;IAC5C,oDAA4C,CAAA;IAE5C,UAAU;IACV,8CAAyC,CAAA;IACzC,8CAAyC,CAAA;IACzC,8CAAyC,CAAA;IAEzC,SAAS;IACT,4CAAwC,CAAA;IACxC,4CAAwC,CAAA;IACxC,4CAAwC,CAAA;IAExC,gBAAgB;IAChB,iDAAsC,CAAA;IACtC,iDAAsC,CAAA;IACtC,iDAAsC,CAAA;IAEtC;;uBAEmB;IAEnB,OAAO;IACP,wCAAqC,CAAA;IACrC,wCAAqC,CAAA;IACrC,wCAAqC,CAAA;IAErC,eAAe;IACf,wDAA6C,CAAA;IAC7C,wDAA6C,CAAA;IAC7C,wDAA6C,CAAA;IAC7C,+EAA+E;IAC/E,oEAAoE;IACpE,0DAA8C,CAAA;IAE9C;;uBAEmB;IAEnB,UAAU;IACV,8CAA0C,CAAA;IAC1C,8CAA0C,CAAA;IAC1C,8CAA0C,CAAA;IAE1C,kBAAkB;IAClB,yDAAgD,CAAA;IAChD,yDAAgD,CAAA;IAChD,yDAAgD,CAAA;IAEhD,iBAAiB;IACjB,6DAAkD,CAAA;IAClD,6DAAkD,CAAA;IAClD,6DAAkD,CAAA;IAElD,kBAAkB;IAClB,2DAAiD,CAAA;IACjD,2DAAiD,CAAA;IACjD,2DAAiD,CAAA;IAEjD,WAAW;IACX,+DAAmD,CAAA;IACnD,+DAAmD,CAAA;IACnD,+DAAmD,CAAA;IAEnD,eAAe;IACf,uDAA+C,CAAA;IAC/C,uDAA+C,CAAA;IAC/C,uDAA+C,CAAA;IAE/C,WAAW;IACX,+DAAmD,CAAA;IACnD,+DAAmD,CAAA;IACnD,+DAAmD,CAAA;IAEnD,UAAU;IACV,6DAAkD,CAAA;IAClD,6DAAkD,CAAA;IAClD,6DAAkD,CAAA;IAElD;;sBAEkB;IAElB,gBAAgB;IAChB,yDAA6C,CAAA;IAC7C,yDAA6C,CAAA;IAC7C,yDAA6C,CAAA;IAE7C,aAAa;IACb,mDAA0C,CAAA;IAC1C,mDAA0C,CAAA;IAC1C,mDAA0C,CAAA;IAE1C;;sBAEkB;IAElB,mBAAmB;IACnB,2CAA2C;IAC3C,2CAA2C;IAC3C,2CAA2C;IAE3C;;sBAEkB;IAElB,0EAA0E;IAC1E,uEAAuE;IACvE,yDAAyD;IACzD,4CAAsC,CAAA;AACxC,CAAC,EAxJW,QAAQ,wBAAR,QAAQ,QAwJnB;AAED,IAAY,cAgBX;AAhBD,WAAY,cAAc;IACxB,yCAAuB,CAAA;IACvB,yCAAuB,CAAA;IACvB,yCAAuB,CAAA;IAEvB;;;;;;;;;OASG;IACH,yCAAuB,CAAA;AACzB,CAAC,EAhBW,cAAc,8BAAd,cAAc,QAgBzB"}
|
|
@@ -38,12 +38,19 @@ export declare function purgeDeadline(purgeValidity?: string | number, from?: Da
|
|
|
38
38
|
* writes the outbox row - so it can only be archived from the document in hand,
|
|
39
39
|
* before or after that call, never by reading it back.
|
|
40
40
|
*
|
|
41
|
+
* WARNING: IDEMPOTENT. A document whose `_id` is already archived for this
|
|
42
|
+
* `(tenantId, sourceCollection)` is skipped rather than filed twice. Redelivery is
|
|
43
|
+
* not hypothetical - `NatsListener` retries three times before the DLQ - and a
|
|
44
|
+
* duplicate entry is not harmless: {@link restoreDocuments} reinserts documents
|
|
45
|
+
* verbatim, `_id` included, so the second copy makes the RESTORE fail on a duplicate
|
|
46
|
+
* key, for the very tenant whose deletion already went wrong.
|
|
47
|
+
*
|
|
41
48
|
* @param archive the shared `tenantArchive` store
|
|
42
49
|
* @param sourceCollection where the documents came from, and where a restore puts them
|
|
43
50
|
* @param documents the documents themselves, archived verbatim
|
|
44
51
|
* @param tenantId the organization being deleted
|
|
45
52
|
* @param purgeAt the shared deadline for the whole cascade
|
|
46
|
-
* @returns how many entries were written
|
|
53
|
+
* @returns how many entries were written, and how many were already there
|
|
47
54
|
*/
|
|
48
55
|
export declare function archiveEntries(archive: TenantArchiveStore, sourceCollection: string, documents: Record<string, unknown>[], tenantId: string, purgeAt: Date): Promise<ArchiveOutcome>;
|
|
49
56
|
/**
|
|
@@ -54,9 +61,14 @@ export declare function archiveEntries(archive: TenantArchiveStore, sourceCollec
|
|
|
54
61
|
* loss, which is exactly what the archive exists to prevent - the same reasoning
|
|
55
62
|
* that puts the organization first in the auth-srv cascade (T29).
|
|
56
63
|
*
|
|
57
|
-
*
|
|
58
|
-
* places, which the restore tolerates (it puts back what is already there, by
|
|
59
|
-
* whereas the opposite ordering would leave them in NEITHER.
|
|
64
|
+
* WARNING: not a transaction. A crash between the two steps leaves the documents in
|
|
65
|
+
* BOTH places, which the restore tolerates (it puts back what is already there, by
|
|
66
|
+
* `_id`) whereas the opposite ordering would leave them in NEITHER.
|
|
67
|
+
*
|
|
68
|
+
* WARNING: the removal is driven by what was FOUND in the source, not by what was
|
|
69
|
+
* written to the archive: on a redelivery every document is already filed, so
|
|
70
|
+
* `archiveEntries` writes nothing, and gating the removal on that count would leave
|
|
71
|
+
* the source full forever - the retry could never converge.
|
|
60
72
|
*
|
|
61
73
|
* The document is archived VERBATIM, `_id` included: relations across collections are
|
|
62
74
|
* by `_id`, so regenerating one would restore a tenant whose relations no longer match.
|
|
@@ -66,7 +78,7 @@ export declare function archiveEntries(archive: TenantArchiveStore, sourceCollec
|
|
|
66
78
|
* @param filter which documents belong to the tenant, as only the caller knows
|
|
67
79
|
* @param tenantId the organization being deleted
|
|
68
80
|
* @param purgeAt the shared deadline for the whole cascade - see {@link purgeDeadline}
|
|
69
|
-
* @returns how many documents were
|
|
81
|
+
* @returns how many documents were archived, and how many were already there
|
|
70
82
|
*/
|
|
71
83
|
export declare function archiveDocuments(source: ArchivableModel, archive: TenantArchiveStore, filter: Record<string, unknown>, tenantId: string, purgeAt: Date): Promise<ArchiveOutcome>;
|
|
72
84
|
/**
|
|
@@ -76,15 +88,23 @@ export declare function archiveDocuments(source: ArchivableModel, archive: Tenan
|
|
|
76
88
|
* reinserted FIRST and the archive entries dropped only afterwards, so a failure
|
|
77
89
|
* leaves them recoverable rather than gone.
|
|
78
90
|
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
91
|
+
* WARNING: IDEMPOTENT, for the mirror image of the reason {@link archiveEntries} is.
|
|
92
|
+
* That same ordering means a crash between the two steps leaves the documents in BOTH
|
|
93
|
+
* places, and the caller is a durable listener, so the message comes back. Reinserting
|
|
94
|
+
* a document that is already there fails on a duplicate `_id` - and it would fail
|
|
95
|
+
* again on every retry, sending to the DLQ the one operation the archive exists to
|
|
96
|
+
* make possible. Documents already back in the source are therefore SKIPPED, and the
|
|
97
|
+
* entries are dropped regardless, so the retry converges.
|
|
98
|
+
*
|
|
99
|
+
* WARNING: restores ONLY what this service owns. The caller passes its own model, and
|
|
100
|
+
* the source collection name it carries is what selects the entries. The shared
|
|
101
|
+
* archive is therefore safe to read from both services - each sees only its own rows,
|
|
102
|
+
* and the two sets are disjoint by construction.
|
|
83
103
|
*
|
|
84
104
|
* @param source the collection being refilled
|
|
85
105
|
* @param archive the shared `tenantArchive` store
|
|
86
106
|
* @param tenantId the organization being restored
|
|
87
|
-
* @returns how many documents were put back
|
|
107
|
+
* @returns how many documents were put back, and how many were already in place
|
|
88
108
|
*/
|
|
89
109
|
export declare function restoreDocuments(source: ArchivableModel, archive: TenantArchiveStore, tenantId: string): Promise<ArchiveOutcome>;
|
|
90
110
|
//# sourceMappingURL=tenant-archive.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant-archive.d.ts","sourceRoot":"","sources":["../../src/services/tenant-archive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;+FAc+F;AAI/F,OAAO,EAAE,eAAe,EAAE,MAAS,6BAA6B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAU,6BAA6B,CAAC;AAEjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAKjE;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,IAAI,CAG5F;AAED
|
|
1
|
+
{"version":3,"file":"tenant-archive.d.ts","sourceRoot":"","sources":["../../src/services/tenant-archive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;+FAc+F;AAI/F,OAAO,EAAE,eAAe,EAAE,MAAS,6BAA6B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAU,6BAA6B,CAAC;AAEjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAKjE;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,IAAI,CAG5F;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAW,kBAAkB,EACpC,gBAAgB,EAAE,MAAM,EACxB,SAAS,EAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC3C,QAAQ,EAAU,MAAM,EACxB,OAAO,EAAW,IAAI,GACrB,OAAO,CAAC,cAAc,CAAC,CAiBzB;AAsDD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAI,eAAe,EACzB,OAAO,EAAG,kBAAkB,EAC5B,MAAM,EAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAG,IAAI,GACb,OAAO,CAAC,cAAc,CAAC,CAWzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAI,eAAe,EACzB,OAAO,EAAG,kBAAkB,EAC5B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,CAAC,CAsBzB"}
|
|
@@ -44,8 +44,20 @@ export interface TenantArchiveStore {
|
|
|
44
44
|
}
|
|
45
45
|
/** What a single archive or restore actually moved. */
|
|
46
46
|
export interface ArchiveOutcome {
|
|
47
|
-
/**
|
|
47
|
+
/** Entries actually written to (or read back from) the archive. */
|
|
48
48
|
moved: number;
|
|
49
|
+
/**
|
|
50
|
+
* Documents NOT re-archived because an entry for the same `_id` was already
|
|
51
|
+
* there.
|
|
52
|
+
*
|
|
53
|
+
* Only ever non-zero on a REDELIVERY: a listener whose archive write succeeded
|
|
54
|
+
* and whose source removal did not gets the message again, finds the documents
|
|
55
|
+
* still in place, and would file a second copy of each. That copy is not
|
|
56
|
+
* harmless - the restore reinserts documents verbatim, `_id` included, so a
|
|
57
|
+
* duplicated entry makes the restore fail on a duplicate key, precisely for the
|
|
58
|
+
* tenant that already had trouble.
|
|
59
|
+
*/
|
|
60
|
+
skipped: number;
|
|
49
61
|
/** The source collection, echoed back so a caller can log the cascade. */
|
|
50
62
|
sourceCollection: string;
|
|
51
63
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant-archive.interfaces.d.ts","sourceRoot":"","sources":["../../src/services/tenant-archive.interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAe;IAE9B,OAAO,EAAE;QACP,UAAU,EAAE;YAAE,cAAc,EAAE,MAAM,CAAA;SAAE,CAAC;KACxC,CAAC;IAEF,UAAU,CAAG,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;KAAE,CAAC;IACjG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAIlF,gBAAgB,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChE;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IAEjC,UAAU,CAAO,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;KAAE,CAAC;IACrG,YAAY,CAAK,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtF,gBAAgB,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChE;AAED,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAE7B,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IAEd,0EAA0E;IAC1E,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,yFAAyF;AACzF,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"tenant-archive.interfaces.d.ts","sourceRoot":"","sources":["../../src/services/tenant-archive.interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAe;IAE9B,OAAO,EAAE;QACP,UAAU,EAAE;YAAE,cAAc,EAAE,MAAM,CAAA;SAAE,CAAC;KACxC,CAAC;IAEF,UAAU,CAAG,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;KAAE,CAAC;IACjG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAIlF,gBAAgB,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChE;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IAEjC,UAAU,CAAO,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;KAAE,CAAC;IACrG,YAAY,CAAK,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtF,gBAAgB,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChE;AAED,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAE7B,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IAEd;;;;;;;;;;OAUG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB,0EAA0E;IAC1E,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,yFAAyF;AACzF,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC"}
|
|
@@ -46,20 +46,68 @@ function purgeDeadline(purgeValidity, from = new Date()) {
|
|
|
46
46
|
* writes the outbox row - so it can only be archived from the document in hand,
|
|
47
47
|
* before or after that call, never by reading it back.
|
|
48
48
|
*
|
|
49
|
+
* WARNING: IDEMPOTENT. A document whose `_id` is already archived for this
|
|
50
|
+
* `(tenantId, sourceCollection)` is skipped rather than filed twice. Redelivery is
|
|
51
|
+
* not hypothetical - `NatsListener` retries three times before the DLQ - and a
|
|
52
|
+
* duplicate entry is not harmless: {@link restoreDocuments} reinserts documents
|
|
53
|
+
* verbatim, `_id` included, so the second copy makes the RESTORE fail on a duplicate
|
|
54
|
+
* key, for the very tenant whose deletion already went wrong.
|
|
55
|
+
*
|
|
49
56
|
* @param archive the shared `tenantArchive` store
|
|
50
57
|
* @param sourceCollection where the documents came from, and where a restore puts them
|
|
51
58
|
* @param documents the documents themselves, archived verbatim
|
|
52
59
|
* @param tenantId the organization being deleted
|
|
53
60
|
* @param purgeAt the shared deadline for the whole cascade
|
|
54
|
-
* @returns how many entries were written
|
|
61
|
+
* @returns how many entries were written, and how many were already there
|
|
55
62
|
*/
|
|
56
63
|
async function archiveEntries(archive, sourceCollection, documents, tenantId, purgeAt) {
|
|
57
64
|
if (!documents.length)
|
|
58
|
-
return { moved: 0, sourceCollection };
|
|
65
|
+
return { moved: 0, skipped: 0, sourceCollection };
|
|
66
|
+
const pending = await withoutAlreadyArchived(archive, sourceCollection, documents, tenantId);
|
|
67
|
+
const skipped = documents.length - pending.length;
|
|
68
|
+
if (!pending.length)
|
|
69
|
+
return { moved: 0, skipped, sourceCollection };
|
|
59
70
|
const archivedAt = new Date();
|
|
60
|
-
const entries =
|
|
71
|
+
const entries = pending.map((doc) => ({ tenantId, sourceCollection, doc, archivedAt, purgeAt }));
|
|
61
72
|
await archive.insertManyNative(entries, {});
|
|
62
|
-
return { moved:
|
|
73
|
+
return { moved: pending.length, skipped, sourceCollection };
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Drops from `documents` the ones already filed for this tenant and collection.
|
|
77
|
+
*
|
|
78
|
+
* Asks the archive only about the `_id`s at hand, rather than reading every entry of
|
|
79
|
+
* the tenant: the cascade files whole collections, so the second form would grow with
|
|
80
|
+
* the tenant instead of with the batch.
|
|
81
|
+
*/
|
|
82
|
+
async function withoutAlreadyArchived(archive, sourceCollection, documents, tenantId) {
|
|
83
|
+
const ids = documents.map(doc => doc._id).filter(id => id !== undefined && id !== null);
|
|
84
|
+
if (!ids.length)
|
|
85
|
+
return documents;
|
|
86
|
+
const filed = await archive.listNative({ tenantId, sourceCollection, 'doc._id': { $in: ids } }).toArray();
|
|
87
|
+
if (!filed.length)
|
|
88
|
+
return documents;
|
|
89
|
+
// Compared as strings: an `_id` is an ObjectId, and two ObjectId instances for
|
|
90
|
+
// the same value are never `===`. Keys that came out empty are dropped, so a
|
|
91
|
+
// document without an `_id` can never match one.
|
|
92
|
+
const already = new Set(filed.map(entry => idKey(entry.doc?._id)).filter(key => !!key));
|
|
93
|
+
return documents.filter(doc => !already.has(idKey(doc._id)));
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The string form of an `_id`, used as a comparison key.
|
|
97
|
+
*
|
|
98
|
+
* Spelled out rather than left to `String(...)` because the documents are typed
|
|
99
|
+
* `Record<string, unknown>`: at runtime an `_id` is an ObjectId, whose `toString`
|
|
100
|
+
* yields the hex form we want, but nothing in the type says so. That gap is not
|
|
101
|
+
* cosmetic - a value stringifying to `'[object Object]'` would give EVERY document
|
|
102
|
+
* the same key, the set would report them all as already archived, and the archive
|
|
103
|
+
* would silently be skipped for the whole collection.
|
|
104
|
+
*
|
|
105
|
+
* @returns the key, or an empty string when there is no id to speak of
|
|
106
|
+
*/
|
|
107
|
+
function idKey(id) {
|
|
108
|
+
if (id === undefined || id === null)
|
|
109
|
+
return '';
|
|
110
|
+
return typeof id === 'string' ? id : id.toString();
|
|
63
111
|
}
|
|
64
112
|
/**
|
|
65
113
|
* Moves every document matching `filter` out of `source` and into the archive.
|
|
@@ -69,9 +117,14 @@ async function archiveEntries(archive, sourceCollection, documents, tenantId, pu
|
|
|
69
117
|
* loss, which is exactly what the archive exists to prevent - the same reasoning
|
|
70
118
|
* that puts the organization first in the auth-srv cascade (T29).
|
|
71
119
|
*
|
|
72
|
-
*
|
|
73
|
-
* places, which the restore tolerates (it puts back what is already there, by
|
|
74
|
-
* whereas the opposite ordering would leave them in NEITHER.
|
|
120
|
+
* WARNING: not a transaction. A crash between the two steps leaves the documents in
|
|
121
|
+
* BOTH places, which the restore tolerates (it puts back what is already there, by
|
|
122
|
+
* `_id`) whereas the opposite ordering would leave them in NEITHER.
|
|
123
|
+
*
|
|
124
|
+
* WARNING: the removal is driven by what was FOUND in the source, not by what was
|
|
125
|
+
* written to the archive: on a redelivery every document is already filed, so
|
|
126
|
+
* `archiveEntries` writes nothing, and gating the removal on that count would leave
|
|
127
|
+
* the source full forever - the retry could never converge.
|
|
75
128
|
*
|
|
76
129
|
* The document is archived VERBATIM, `_id` included: relations across collections are
|
|
77
130
|
* by `_id`, so regenerating one would restore a tenant whose relations no longer match.
|
|
@@ -81,13 +134,13 @@ async function archiveEntries(archive, sourceCollection, documents, tenantId, pu
|
|
|
81
134
|
* @param filter which documents belong to the tenant, as only the caller knows
|
|
82
135
|
* @param tenantId the organization being deleted
|
|
83
136
|
* @param purgeAt the shared deadline for the whole cascade - see {@link purgeDeadline}
|
|
84
|
-
* @returns how many documents were
|
|
137
|
+
* @returns how many documents were archived, and how many were already there
|
|
85
138
|
*/
|
|
86
139
|
async function archiveDocuments(source, archive, filter, tenantId, purgeAt) {
|
|
87
140
|
const sourceCollection = source.mgModel.collection.collectionName;
|
|
88
141
|
const documents = await source.listNative(filter).toArray();
|
|
89
142
|
const outcome = await archiveEntries(archive, sourceCollection, documents, tenantId, purgeAt);
|
|
90
|
-
if (
|
|
143
|
+
if (documents.length)
|
|
91
144
|
await source.removeNative(filter);
|
|
92
145
|
return outcome;
|
|
93
146
|
}
|
|
@@ -98,23 +151,56 @@ async function archiveDocuments(source, archive, filter, tenantId, purgeAt) {
|
|
|
98
151
|
* reinserted FIRST and the archive entries dropped only afterwards, so a failure
|
|
99
152
|
* leaves them recoverable rather than gone.
|
|
100
153
|
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
154
|
+
* WARNING: IDEMPOTENT, for the mirror image of the reason {@link archiveEntries} is.
|
|
155
|
+
* That same ordering means a crash between the two steps leaves the documents in BOTH
|
|
156
|
+
* places, and the caller is a durable listener, so the message comes back. Reinserting
|
|
157
|
+
* a document that is already there fails on a duplicate `_id` - and it would fail
|
|
158
|
+
* again on every retry, sending to the DLQ the one operation the archive exists to
|
|
159
|
+
* make possible. Documents already back in the source are therefore SKIPPED, and the
|
|
160
|
+
* entries are dropped regardless, so the retry converges.
|
|
161
|
+
*
|
|
162
|
+
* WARNING: restores ONLY what this service owns. The caller passes its own model, and
|
|
163
|
+
* the source collection name it carries is what selects the entries. The shared
|
|
164
|
+
* archive is therefore safe to read from both services - each sees only its own rows,
|
|
165
|
+
* and the two sets are disjoint by construction.
|
|
105
166
|
*
|
|
106
167
|
* @param source the collection being refilled
|
|
107
168
|
* @param archive the shared `tenantArchive` store
|
|
108
169
|
* @param tenantId the organization being restored
|
|
109
|
-
* @returns how many documents were put back
|
|
170
|
+
* @returns how many documents were put back, and how many were already in place
|
|
110
171
|
*/
|
|
111
172
|
async function restoreDocuments(source, archive, tenantId) {
|
|
112
173
|
const sourceCollection = source.mgModel.collection.collectionName;
|
|
113
174
|
const entries = await archive.listNative({ tenantId, sourceCollection }).toArray();
|
|
114
175
|
if (!entries.length)
|
|
115
|
-
return { moved: 0, sourceCollection };
|
|
116
|
-
|
|
176
|
+
return { moved: 0, skipped: 0, sourceCollection };
|
|
177
|
+
const documents = entries.map(entry => entry.doc);
|
|
178
|
+
const pending = await withoutAlreadyRestored(source, documents);
|
|
179
|
+
const skipped = documents.length - pending.length;
|
|
180
|
+
if (pending.length)
|
|
181
|
+
await source.insertManyNative(pending, {});
|
|
182
|
+
// Dropped even when nothing was reinserted: on a redelivery everything is
|
|
183
|
+
// already back, and leaving the entries would keep the tenant looking
|
|
184
|
+
// half-restored - and would keep the TTL index pointed at documents that are
|
|
185
|
+
// once again live.
|
|
117
186
|
await archive.removeNative({ tenantId, sourceCollection });
|
|
118
|
-
return { moved:
|
|
187
|
+
return { moved: pending.length, skipped, sourceCollection };
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Drops from `documents` the ones already sitting in `source`.
|
|
191
|
+
*
|
|
192
|
+
* Asks the source only about the `_id`s at hand, for the same reason
|
|
193
|
+
* {@link withoutAlreadyArchived} does: the batch is what bounds the query, not the
|
|
194
|
+
* size of the tenant.
|
|
195
|
+
*/
|
|
196
|
+
async function withoutAlreadyRestored(source, documents) {
|
|
197
|
+
const ids = documents.map(doc => doc._id).filter(id => id !== undefined && id !== null);
|
|
198
|
+
if (!ids.length)
|
|
199
|
+
return documents;
|
|
200
|
+
const present = await source.listNative({ _id: { $in: ids } }).toArray();
|
|
201
|
+
if (!present.length)
|
|
202
|
+
return documents;
|
|
203
|
+
const already = new Set(present.map(doc => idKey(doc._id)).filter(key => !!key));
|
|
204
|
+
return documents.filter(doc => !already.has(idKey(doc._id)));
|
|
119
205
|
}
|
|
120
206
|
//# sourceMappingURL=tenant-archive.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant-archive.js","sourceRoot":"","sources":["../../src/services/tenant-archive.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;+FAc+F;;AAwB/F,sCAGC;
|
|
1
|
+
{"version":3,"file":"tenant-archive.js","sourceRoot":"","sources":["../../src/services/tenant-archive.ts"],"names":[],"mappings":"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"}
|