@marinoscar/platform-api 0.1.0-next.25 → 0.1.0-next.27

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.
Files changed (118) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/identity/auth/decorators/current-user.decorator.d.ts +30 -5
  3. package/dist/identity/auth/decorators/current-user.decorator.d.ts.map +1 -1
  4. package/dist/identity/auth/decorators/current-user.decorator.js +31 -6
  5. package/dist/identity/auth/decorators/current-user.decorator.js.map +1 -1
  6. package/dist/manifest/platform-model-ownership.d.ts.map +1 -1
  7. package/dist/manifest/platform-model-ownership.js +19 -0
  8. package/dist/manifest/platform-model-ownership.js.map +1 -1
  9. package/dist/manifest/platform-user-owned-models.d.ts.map +1 -1
  10. package/dist/manifest/platform-user-owned-models.js +15 -0
  11. package/dist/manifest/platform-user-owned-models.js.map +1 -1
  12. package/dist/notifications/dto/notification.dto.d.ts +24 -2
  13. package/dist/notifications/dto/notification.dto.d.ts.map +1 -1
  14. package/dist/notifications/dto/notification.dto.js +19 -1
  15. package/dist/notifications/dto/notification.dto.js.map +1 -1
  16. package/dist/notifications/index.d.ts +3 -2
  17. package/dist/notifications/index.d.ts.map +1 -1
  18. package/dist/notifications/index.js +9 -2
  19. package/dist/notifications/index.js.map +1 -1
  20. package/dist/notifications/notification-dismissal.d.ts +49 -0
  21. package/dist/notifications/notification-dismissal.d.ts.map +1 -0
  22. package/dist/notifications/notification-dismissal.js +109 -0
  23. package/dist/notifications/notification-dismissal.js.map +1 -0
  24. package/dist/notifications/notification-store.service.d.ts +12 -0
  25. package/dist/notifications/notification-store.service.d.ts.map +1 -1
  26. package/dist/notifications/notification-store.service.js +32 -6
  27. package/dist/notifications/notification-store.service.js.map +1 -1
  28. package/dist/notifications/notification-stream.service.d.ts +42 -1
  29. package/dist/notifications/notification-stream.service.d.ts.map +1 -1
  30. package/dist/notifications/notification-stream.service.js +97 -4
  31. package/dist/notifications/notification-stream.service.js.map +1 -1
  32. package/dist/notifications/notifications.controller.d.ts +2 -1
  33. package/dist/notifications/notifications.controller.d.ts.map +1 -1
  34. package/dist/notifications/notifications.controller.js +44 -3
  35. package/dist/notifications/notifications.controller.js.map +1 -1
  36. package/dist/notifications/notifications.system-settings.d.ts +13 -0
  37. package/dist/notifications/notifications.system-settings.d.ts.map +1 -1
  38. package/dist/notifications/notifications.system-settings.js +10 -0
  39. package/dist/notifications/notifications.system-settings.js.map +1 -1
  40. package/dist/notifications/notifications.user-settings.d.ts +8 -0
  41. package/dist/notifications/notifications.user-settings.d.ts.map +1 -1
  42. package/dist/notifications/notifications.user-settings.js +11 -0
  43. package/dist/notifications/notifications.user-settings.js.map +1 -1
  44. package/dist/settings/data/settings-db.d.ts +28 -0
  45. package/dist/settings/data/settings-db.d.ts.map +1 -1
  46. package/dist/settings/index.d.ts +2 -1
  47. package/dist/settings/index.d.ts.map +1 -1
  48. package/dist/settings/index.js.map +1 -1
  49. package/dist/settings/registry/system-settings-namespace.d.ts +9 -0
  50. package/dist/settings/registry/system-settings-namespace.d.ts.map +1 -1
  51. package/dist/settings/registry/system-settings-namespace.js +2 -0
  52. package/dist/settings/registry/system-settings-namespace.js.map +1 -1
  53. package/dist/settings/registry/user-settings-namespace.d.ts +9 -0
  54. package/dist/settings/registry/user-settings-namespace.d.ts.map +1 -1
  55. package/dist/settings/registry/user-settings-namespace.js +3 -0
  56. package/dist/settings/registry/user-settings-namespace.js.map +1 -1
  57. package/dist/settings/system-settings/system-settings.service.d.ts +7 -0
  58. package/dist/settings/system-settings/system-settings.service.d.ts.map +1 -1
  59. package/dist/settings/system-settings/system-settings.service.js +22 -4
  60. package/dist/settings/system-settings/system-settings.service.js.map +1 -1
  61. package/dist/settings/user-settings/user-settings.service.d.ts +9 -0
  62. package/dist/settings/user-settings/user-settings.service.d.ts.map +1 -1
  63. package/dist/settings/user-settings/user-settings.service.js +24 -4
  64. package/dist/settings/user-settings/user-settings.service.js.map +1 -1
  65. package/dist/settings/write-hooks.d.ts +53 -0
  66. package/dist/settings/write-hooks.d.ts.map +1 -0
  67. package/dist/settings/write-hooks.js +55 -0
  68. package/dist/settings/write-hooks.js.map +1 -0
  69. package/dist/storage/config/storage-config.module.d.ts.map +1 -1
  70. package/dist/storage/config/storage-config.module.js +10 -1
  71. package/dist/storage/config/storage-config.module.js.map +1 -1
  72. package/dist/storage/data/storage-db.d.ts +118 -1
  73. package/dist/storage/data/storage-db.d.ts.map +1 -1
  74. package/dist/storage/data/storage-db.js +25 -1
  75. package/dist/storage/data/storage-db.js.map +1 -1
  76. package/dist/storage/index.d.ts +5 -2
  77. package/dist/storage/index.d.ts.map +1 -1
  78. package/dist/storage/index.js +25 -1
  79. package/dist/storage/index.js.map +1 -1
  80. package/dist/storage/migration/copy-and-verify.d.ts +39 -0
  81. package/dist/storage/migration/copy-and-verify.d.ts.map +1 -0
  82. package/dist/storage/migration/copy-and-verify.js +94 -0
  83. package/dist/storage/migration/copy-and-verify.js.map +1 -0
  84. package/dist/storage/migration/dto/storage-migration.dto.d.ts +73 -0
  85. package/dist/storage/migration/dto/storage-migration.dto.d.ts.map +1 -0
  86. package/dist/storage/migration/dto/storage-migration.dto.js +34 -0
  87. package/dist/storage/migration/dto/storage-migration.dto.js.map +1 -0
  88. package/dist/storage/migration/index.d.ts +11 -0
  89. package/dist/storage/migration/index.d.ts.map +1 -0
  90. package/dist/storage/migration/index.js +27 -0
  91. package/dist/storage/migration/index.js.map +1 -0
  92. package/dist/storage/migration/storage-migrate-object.handler.d.ts +40 -0
  93. package/dist/storage/migration/storage-migrate-object.handler.d.ts.map +1 -0
  94. package/dist/storage/migration/storage-migrate-object.handler.js +177 -0
  95. package/dist/storage/migration/storage-migrate-object.handler.js.map +1 -0
  96. package/dist/storage/migration/storage-migrate-plan.handler.d.ts +34 -0
  97. package/dist/storage/migration/storage-migrate-plan.handler.d.ts.map +1 -0
  98. package/dist/storage/migration/storage-migrate-plan.handler.js +168 -0
  99. package/dist/storage/migration/storage-migrate-plan.handler.js.map +1 -0
  100. package/dist/storage/migration/storage-migration-settled.listener.d.ts +15 -0
  101. package/dist/storage/migration/storage-migration-settled.listener.d.ts.map +1 -0
  102. package/dist/storage/migration/storage-migration-settled.listener.js +87 -0
  103. package/dist/storage/migration/storage-migration-settled.listener.js.map +1 -0
  104. package/dist/storage/migration/storage-migration.constants.d.ts +69 -0
  105. package/dist/storage/migration/storage-migration.constants.d.ts.map +1 -0
  106. package/dist/storage/migration/storage-migration.constants.js +83 -0
  107. package/dist/storage/migration/storage-migration.constants.js.map +1 -0
  108. package/dist/storage/migration/storage-migration.controller.d.ts +26 -0
  109. package/dist/storage/migration/storage-migration.controller.d.ts.map +1 -0
  110. package/dist/storage/migration/storage-migration.controller.js +135 -0
  111. package/dist/storage/migration/storage-migration.controller.js.map +1 -0
  112. package/dist/storage/migration/storage-migration.service.d.ts +182 -0
  113. package/dist/storage/migration/storage-migration.service.d.ts.map +1 -0
  114. package/dist/storage/migration/storage-migration.service.js +444 -0
  115. package/dist/storage/migration/storage-migration.service.js.map +1 -0
  116. package/dist/storage/ports.d.ts +1 -1
  117. package/dist/storage/ports.d.ts.map +1 -1
  118. package/package.json +3 -3
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ // =============================================================================
3
+ // `storage.migrate_object` — copy one object to the run's target driver,
4
+ // verify it, repoint its row, leave the source (issue #1093)
5
+ // =============================================================================
6
+ //
7
+ // ORDER, AND WHY IT IS THE WHOLE DESIGN
8
+ //
9
+ // 1. The run must still be running. A cancelled (or finished) run's item is
10
+ // marked `skipped` and nothing is copied: a cancelled run stops before its
11
+ // next unclaimed object.
12
+ // 2. The item and its object are read in the object's organization
13
+ // (`JobScope.run`, the job carries the object's `orgId`). An object that is
14
+ // gone, not `ready`, or no longer recorded on the source (repointed by an
15
+ // earlier run, re-uploaded elsewhere) is `skipped`: a re-run never copies
16
+ // an already-migrated object twice.
17
+ // 3. The bytes are STREAMED from the source into the target and read back
18
+ // (`copyAndVerify`): the byte count and the sha256 must agree on both sides
19
+ // and with the row's size. Nothing is buffered.
20
+ // 4. Only then is the row repointed, in one org-scoped transaction, guarded by
21
+ // `storage_provider = source AND storage_key = key`: an object changed while
22
+ // it was being copied is not repointed (it is `skipped`), so the row never
23
+ // points at bytes that are not its own.
24
+ // 5. The source object is NEVER deleted: it is the fallback.
25
+ //
26
+ // FAILURE. A thrown error (a network glitch, throttling, a verification
27
+ // mismatch) is retried by the queue with backoff; the item stays `copying`.
28
+ // When the job gives up, `StorageMigrationSettledListener` marks a still-open item `failed` — a
29
+ // listener rather than an "is this my last attempt?" check, because a timeout
30
+ // or a dead executor never returns into `process`.
31
+ //
32
+ // SERVER-ONLY BY DERIVATION: neither `nodeResultSchema` nor `persistNodeResult`.
33
+ // The copy needs BOTH drivers' secrets, which are never brokered to a worker
34
+ // node.
35
+ // =============================================================================
36
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
37
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
38
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
39
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
40
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
41
+ };
42
+ var __metadata = (this && this.__metadata) || function (k, v) {
43
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
44
+ };
45
+ var StorageMigrateObjectHandler_1;
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.StorageMigrateObjectHandler = void 0;
48
+ const common_1 = require("@nestjs/common");
49
+ const index_1 = require("../../jobs/index");
50
+ const storage_config_service_1 = require("../config/storage-config.service");
51
+ const storage_db_1 = require("../data/storage-db");
52
+ const storage_provider_router_1 = require("../providers/storage-provider-router");
53
+ const copy_and_verify_1 = require("./copy-and-verify");
54
+ const storage_migration_constants_1 = require("./storage-migration.constants");
55
+ const storage_migration_service_1 = require("./storage-migration.service");
56
+ function readPayload(job) {
57
+ const payload = job.payload;
58
+ if (!payload || typeof payload.runId !== 'string' || typeof payload.itemId !== 'string') {
59
+ throw new Error(`${storage_migration_constants_1.STORAGE_MIGRATE_OBJECT_TYPE} job ${job.id} has an invalid payload`);
60
+ }
61
+ return { runId: payload.runId, itemId: payload.itemId };
62
+ }
63
+ /**
64
+ * The server-only `storage.migrate_object` job: streams one object from the run's source driver to its target, verifies size and sha256 by reading it back, repoints the row and leaves the source in place.
65
+ *
66
+ * @stability experimental
67
+ */
68
+ let StorageMigrateObjectHandler = StorageMigrateObjectHandler_1 = class StorageMigrateObjectHandler {
69
+ registry;
70
+ migrations;
71
+ jobScope;
72
+ router;
73
+ storageConfig;
74
+ logger = new common_1.Logger(StorageMigrateObjectHandler_1.name);
75
+ type = storage_migration_constants_1.STORAGE_MIGRATE_OBJECT_TYPE;
76
+ label = 'Storage migration (copy object)';
77
+ /** One object can be several gigabytes, copied and then read back. */
78
+ profile = { maxRuntimeMs: 60 * 60_000, maxAttempts: 3 };
79
+ constructor(registry, migrations, jobScope, router, storageConfig) {
80
+ this.registry = registry;
81
+ this.migrations = migrations;
82
+ this.jobScope = jobScope;
83
+ this.router = router;
84
+ this.storageConfig = storageConfig;
85
+ }
86
+ /** Self-registration. */
87
+ onModuleInit() {
88
+ this.registry.register(this);
89
+ }
90
+ /** Copies, verifies and repoints the job's object; see the file header. */
91
+ async process(job) {
92
+ const { runId, itemId } = readPayload(job);
93
+ const run = await this.migrations.db().storageMigrationRun.findUnique({ where: { id: runId } });
94
+ if (!run)
95
+ return;
96
+ const claim = await this.jobScope.run(job, async (tx) => {
97
+ const item = await tx.storageMigrationItem.findUnique({ where: { id: itemId } });
98
+ if (!item || (item.status !== storage_db_1.StorageMigrationItemStatus.pending && item.status !== storage_db_1.StorageMigrationItemStatus.copying)) {
99
+ return { kind: 'done' };
100
+ }
101
+ if (run.status !== storage_db_1.StorageMigrationRunStatus.running) {
102
+ await this.skip(tx, itemId, `Run ${run.status}`);
103
+ return { kind: 'skipped' };
104
+ }
105
+ const object = await tx.storageObject.findUnique({ where: { id: item.objectId } });
106
+ if (!object || object.status !== storage_db_1.StorageObjectStatus.ready) {
107
+ await this.skip(tx, itemId, 'The object is gone or not ready');
108
+ return { kind: 'skipped' };
109
+ }
110
+ if (object.storageProvider !== run.sourceProvider) {
111
+ await this.skip(tx, itemId, `The object is recorded on "${object.storageProvider}", not on the source`);
112
+ return { kind: 'skipped' };
113
+ }
114
+ await tx.storageMigrationItem.update({ where: { id: itemId }, data: { status: storage_db_1.StorageMigrationItemStatus.copying } });
115
+ return { kind: 'copy', object };
116
+ });
117
+ if (claim.kind === 'done')
118
+ return;
119
+ if (claim.kind === 'skipped') {
120
+ await this.migrations.finalizeIfDone(runId);
121
+ return;
122
+ }
123
+ const { object } = claim;
124
+ // Both drivers must be buildable: the router would serve an unbuildable one
125
+ // with the ACTIVE provider, which is the wrong place to read or write.
126
+ for (const provider of [run.sourceProvider, run.targetProvider]) {
127
+ const resolution = await this.storageConfig.resolveDriver(provider);
128
+ if (!resolution.configured) {
129
+ throw new Error(`Storage driver "${provider}" is not configured (missing ${resolution.missing.join(', ')})`);
130
+ }
131
+ }
132
+ const source = await this.router.forObject(object);
133
+ const target = await this.router.forLocation({ provider: run.targetProvider, bucket: '' });
134
+ const verified = await (0, copy_and_verify_1.copyAndVerify)(source, target, object);
135
+ const targetBucket = target.getBucket();
136
+ const repointed = await this.jobScope.run(job, async (tx) => {
137
+ const moved = await tx.storageObject.updateMany({
138
+ where: { id: object.id, storageProvider: run.sourceProvider, storageKey: object.storageKey },
139
+ data: { storageProvider: run.targetProvider, bucket: targetBucket },
140
+ });
141
+ if (moved.count === 0) {
142
+ await this.skip(tx, itemId, 'The object changed while it was being copied; not repointed');
143
+ return false;
144
+ }
145
+ await tx.storageMigrationItem.update({
146
+ where: { id: itemId },
147
+ data: {
148
+ status: storage_db_1.StorageMigrationItemStatus.migrated,
149
+ sizeBytes: verified.bytes,
150
+ checksumSha256: verified.sha256,
151
+ lastError: null,
152
+ },
153
+ });
154
+ return true;
155
+ });
156
+ if (repointed) {
157
+ this.logger.log(`Storage migration ${runId}: object ${object.id} copied ${run.sourceProvider} -> ${run.targetProvider} (${verified.bytes} bytes, verified)`);
158
+ }
159
+ await this.migrations.finalizeIfDone(runId);
160
+ }
161
+ async skip(tx, itemId, reason) {
162
+ await tx.storageMigrationItem.update({
163
+ where: { id: itemId },
164
+ data: { status: storage_db_1.StorageMigrationItemStatus.skipped, lastError: reason },
165
+ });
166
+ }
167
+ };
168
+ exports.StorageMigrateObjectHandler = StorageMigrateObjectHandler;
169
+ exports.StorageMigrateObjectHandler = StorageMigrateObjectHandler = StorageMigrateObjectHandler_1 = __decorate([
170
+ (0, common_1.Injectable)(),
171
+ __metadata("design:paramtypes", [index_1.JobHandlerRegistry,
172
+ storage_migration_service_1.StorageMigrationService,
173
+ index_1.JobScope,
174
+ storage_provider_router_1.StorageProviderRouter,
175
+ storage_config_service_1.StorageConfigService])
176
+ ], StorageMigrateObjectHandler);
177
+ //# sourceMappingURL=storage-migrate-object.handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-migrate-object.handler.js","sourceRoot":"","sources":["../../../src/storage/migration/storage-migrate-object.handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { OnModuleInit } from '@nestjs/common';
2
+ import { JobHandlerRegistry, JobsService, type Job, type JobExecutionProfile, type JobHandler } from '../../jobs/index';
3
+ import { StorageMigrationService } from './storage-migration.service';
4
+ /**
5
+ * The planner job's payload.
6
+ *
7
+ * @stability experimental
8
+ */
9
+ export interface StorageMigratePlanPayload {
10
+ /** The run to plan. */
11
+ runId: string;
12
+ }
13
+ /**
14
+ * The server-only `storage.migrate_plan` job: creates one item per `ready` object on the run's source driver and queues one `storage.migrate_object` job per item, resumably; a planner that gives up fails its run.
15
+ *
16
+ * @stability experimental
17
+ */
18
+ export declare class StorageMigratePlanHandler implements JobHandler, OnModuleInit {
19
+ private readonly registry;
20
+ private readonly migrations;
21
+ private readonly jobs;
22
+ private readonly logger;
23
+ readonly type = "storage.migrate_plan";
24
+ readonly label = "Storage migration (plan)";
25
+ /** Listing and queueing a large deployment's objects is long but bounded work. */
26
+ readonly profile: JobExecutionProfile;
27
+ constructor(registry: JobHandlerRegistry, migrations: StorageMigrationService, jobs: JobsService);
28
+ /** Self-registration. */
29
+ onModuleInit(): void;
30
+ /** Plans the run named in the payload. */
31
+ process(job: Job): Promise<void>;
32
+ private cancelled;
33
+ }
34
+ //# sourceMappingURL=storage-migrate-plan.handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-migrate-plan.handler.d.ts","sourceRoot":"","sources":["../../../src/storage/migration/storage-migrate-plan.handler.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAsB,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAElE,OAAO,EACL,kBAAkB,EAElB,WAAW,EACX,KAAK,GAAG,EACR,KAAK,mBAAmB,EACxB,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAC;AAQ1B,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAKtE;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AAUD;;;;GAIG;AACH,qBACa,yBAA0B,YAAW,UAAU,EAAE,YAAY;IAWtE,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI;IAZvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8C;IAErE,QAAQ,CAAC,IAAI,0BAA6B;IAE1C,QAAQ,CAAC,KAAK,8BAA8B;IAE5C,kFAAkF;IAClF,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAiD;gBAGnE,QAAQ,EAAE,kBAAkB,EAC5B,UAAU,EAAE,uBAAuB,EACnC,IAAI,EAAE,WAAW;IAGpC,yBAAyB;IACzB,YAAY,IAAI,IAAI;IAIpB,0CAA0C;IACpC,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;YAoFxB,SAAS;CAIxB"}
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ // =============================================================================
3
+ // `storage.migrate_plan` — list a migration run's objects and queue them
4
+ // (issue #1093)
5
+ // =============================================================================
6
+ //
7
+ // One job per run, a system job (`orgId: null`): the run is deployment-wide and
8
+ // its objects belong to every organization, so it works through the bypass
9
+ // client with the `storage-migration` reason.
10
+ //
11
+ // RESUMABLE. Items are created page by page (keyset on the object id) with
12
+ // `skipDuplicates` against `@@unique([runId, objectId])`, and only items with no
13
+ // `jobId` are queued, so a planner that died half way and was retried continues
14
+ // where it stopped without a duplicate item or a duplicate job.
15
+ //
16
+ // WHAT IS COPIED: every `ready` object whose recorded `storage_provider` is the
17
+ // run's source. An object already repointed to the target is not on the source
18
+ // any more, so a re-run after a completed or cancelled run skips it for free.
19
+ //
20
+ // CANCELLATION is checked before every page; a cancelled run stops planning.
21
+ //
22
+ // SERVER-ONLY BY DERIVATION: no `nodeResultSchema` / `persistNodeResult`.
23
+ // =============================================================================
24
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
25
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
26
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
27
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
28
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
29
+ };
30
+ var __metadata = (this && this.__metadata) || function (k, v) {
31
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
32
+ };
33
+ var StorageMigratePlanHandler_1;
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.StorageMigratePlanHandler = void 0;
36
+ const common_1 = require("@nestjs/common");
37
+ const index_1 = require("../../jobs/index");
38
+ const storage_db_1 = require("../data/storage-db");
39
+ const storage_migration_constants_1 = require("./storage-migration.constants");
40
+ const storage_migration_service_1 = require("./storage-migration.service");
41
+ /** Objects listed, and items queued, per page. */
42
+ const PAGE_SIZE = 500;
43
+ function readRunId(job) {
44
+ const payload = job.payload;
45
+ if (!payload || typeof payload.runId !== 'string') {
46
+ throw new Error(`${storage_migration_constants_1.STORAGE_MIGRATE_PLAN_TYPE} job ${job.id} has no runId in its payload`);
47
+ }
48
+ return payload.runId;
49
+ }
50
+ /**
51
+ * The server-only `storage.migrate_plan` job: creates one item per `ready` object on the run's source driver and queues one `storage.migrate_object` job per item, resumably; a planner that gives up fails its run.
52
+ *
53
+ * @stability experimental
54
+ */
55
+ let StorageMigratePlanHandler = StorageMigratePlanHandler_1 = class StorageMigratePlanHandler {
56
+ registry;
57
+ migrations;
58
+ jobs;
59
+ logger = new common_1.Logger(StorageMigratePlanHandler_1.name);
60
+ type = storage_migration_constants_1.STORAGE_MIGRATE_PLAN_TYPE;
61
+ label = 'Storage migration (plan)';
62
+ /** Listing and queueing a large deployment's objects is long but bounded work. */
63
+ profile = { maxRuntimeMs: 60 * 60_000, maxAttempts: 3 };
64
+ constructor(registry, migrations, jobs) {
65
+ this.registry = registry;
66
+ this.migrations = migrations;
67
+ this.jobs = jobs;
68
+ }
69
+ /** Self-registration. */
70
+ onModuleInit() {
71
+ this.registry.register(this);
72
+ }
73
+ /** Plans the run named in the payload. */
74
+ async process(job) {
75
+ const runId = readRunId(job);
76
+ const db = this.migrations.db();
77
+ const run = await db.storageMigrationRun.findUnique({ where: { id: runId } });
78
+ if (!run) {
79
+ this.logger.warn(`${this.type} job ${job.id}: run ${runId} no longer exists; nothing to plan`);
80
+ return;
81
+ }
82
+ if (run.status !== storage_db_1.StorageMigrationRunStatus.pending && run.status !== storage_db_1.StorageMigrationRunStatus.running) {
83
+ this.logger.log(`${this.type} job ${job.id}: run ${runId} is ${run.status}; nothing to plan`);
84
+ return;
85
+ }
86
+ await db.storageMigrationRun.updateMany({
87
+ where: { id: runId, status: storage_db_1.StorageMigrationRunStatus.pending },
88
+ data: { status: storage_db_1.StorageMigrationRunStatus.running, startedAt: new Date() },
89
+ });
90
+ // 1. One item per object on the source, keyset-paged.
91
+ let cursor;
92
+ for (;;) {
93
+ if (await this.cancelled(runId))
94
+ return;
95
+ const objects = await db.storageObject.findMany({
96
+ where: {
97
+ storageProvider: run.sourceProvider,
98
+ status: storage_db_1.StorageObjectStatus.ready,
99
+ ...(cursor ? { id: { gt: cursor } } : {}),
100
+ },
101
+ select: { id: true, orgId: true, size: true },
102
+ orderBy: { id: 'asc' },
103
+ take: PAGE_SIZE,
104
+ });
105
+ if (objects.length === 0)
106
+ break;
107
+ await db.storageMigrationItem.createMany({
108
+ data: objects.map((object) => ({
109
+ runId,
110
+ objectId: object.id,
111
+ orgId: object.orgId,
112
+ sizeBytes: object.size,
113
+ status: storage_db_1.StorageMigrationItemStatus.pending,
114
+ })),
115
+ skipDuplicates: true,
116
+ });
117
+ cursor = objects[objects.length - 1].id;
118
+ if (objects.length < PAGE_SIZE)
119
+ break;
120
+ }
121
+ // 2. One job per item that has none yet.
122
+ for (;;) {
123
+ if (await this.cancelled(runId))
124
+ return;
125
+ const items = await db.storageMigrationItem.findMany({
126
+ where: { runId, jobId: null, status: storage_db_1.StorageMigrationItemStatus.pending },
127
+ select: { id: true, objectId: true, orgId: true },
128
+ orderBy: { id: 'asc' },
129
+ take: PAGE_SIZE,
130
+ });
131
+ if (items.length === 0)
132
+ break;
133
+ for (const item of items) {
134
+ const queued = await this.jobs.enqueue({
135
+ type: storage_migration_constants_1.STORAGE_MIGRATE_OBJECT_TYPE,
136
+ reason: index_1.JobReason.backfill,
137
+ subjectType: storage_migration_constants_1.STORAGE_MIGRATION_ITEM_SUBJECT_TYPE,
138
+ subjectId: item.id,
139
+ payload: { runId, itemId: item.id },
140
+ priority: storage_migration_constants_1.STORAGE_MIGRATION_PRIORITY,
141
+ orgId: item.orgId,
142
+ skipDedup: true,
143
+ });
144
+ await db.storageMigrationItem.updateMany({ where: { id: item.id, jobId: null }, data: { jobId: queued.id } });
145
+ }
146
+ }
147
+ const total = await db.storageMigrationItem.count({ where: { runId } });
148
+ await db.storageMigrationRun.updateMany({
149
+ where: { id: runId, status: storage_db_1.StorageMigrationRunStatus.running },
150
+ data: { plannedAt: new Date(), totalCount: total },
151
+ });
152
+ this.logger.log(`Storage migration ${runId}: ${total} object(s) queued (${run.sourceProvider} -> ${run.targetProvider})`);
153
+ // Every item may already be done (or there were none): finalize now.
154
+ await this.migrations.finalizeIfDone(runId);
155
+ }
156
+ async cancelled(runId) {
157
+ const current = await this.migrations.db().storageMigrationRun.findUnique({ where: { id: runId }, select: { status: true } });
158
+ return !current || current.status !== storage_db_1.StorageMigrationRunStatus.running;
159
+ }
160
+ };
161
+ exports.StorageMigratePlanHandler = StorageMigratePlanHandler;
162
+ exports.StorageMigratePlanHandler = StorageMigratePlanHandler = StorageMigratePlanHandler_1 = __decorate([
163
+ (0, common_1.Injectable)(),
164
+ __metadata("design:paramtypes", [index_1.JobHandlerRegistry,
165
+ storage_migration_service_1.StorageMigrationService,
166
+ index_1.JobsService])
167
+ ], StorageMigratePlanHandler);
168
+ //# sourceMappingURL=storage-migrate-plan.handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-migrate-plan.handler.js","sourceRoot":"","sources":["../../../src/storage/migration/storage-migrate-plan.handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { type JobSettledEvent } from '../../jobs/index';
2
+ import { StorageMigrationService } from './storage-migration.service';
3
+ /**
4
+ * Fails the run of a planner that gave up, and the item of an object job that gave up.
5
+ *
6
+ * @stability experimental
7
+ */
8
+ export declare class StorageMigrationSettledListener {
9
+ private readonly migrations;
10
+ private readonly logger;
11
+ constructor(migrations: StorageMigrationService);
12
+ /** Dispatches a failed migration job; ignores everything else. Never throws. */
13
+ onJobSettled(event: JobSettledEvent): Promise<void>;
14
+ }
15
+ //# sourceMappingURL=storage-migration-settled.listener.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-migration-settled.listener.d.ts","sourceRoot":"","sources":["../../../src/storage/migration/storage-migration-settled.listener.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAQ3E,OAAO,EAAE,uBAAuB,EAA6B,MAAM,6BAA6B,CAAC;AAEjG;;;;GAIG;AACH,qBACa,+BAA+B;IAG9B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAFvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoD;gBAE9C,UAAU,EAAE,uBAAuB;IAEhE,gFAAgF;IAE1E,YAAY,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CA6B1D"}
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ // =============================================================================
3
+ // StorageMigrationSettledListener: what happens when a migration job GIVES UP
4
+ // (issue #1093)
5
+ // =============================================================================
6
+ //
7
+ // A listener on `job.settled`, not an "is this my last attempt?" check inside
8
+ // `process`: a timeout or a dead executor never returns into `process`. ONE
9
+ // listener for both job types (the event has a bounded listener budget), and a
10
+ // few bounded writes each, never I/O (`on-event-no-io`):
11
+ //
12
+ // * `storage.migrate_plan` failed: the run is failed (its active slot freed,
13
+ // its queued items skipped).
14
+ // * `storage.migrate_object` failed: its still-open item is failed, the error
15
+ // recorded on the run, and the run finalized when that was the last item.
16
+ // =============================================================================
17
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
18
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
21
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
22
+ };
23
+ var __metadata = (this && this.__metadata) || function (k, v) {
24
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
25
+ };
26
+ var StorageMigrationSettledListener_1;
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.StorageMigrationSettledListener = void 0;
29
+ const common_1 = require("@nestjs/common");
30
+ const event_emitter_1 = require("@nestjs/event-emitter");
31
+ const index_1 = require("../../jobs/index");
32
+ const storage_db_1 = require("../data/storage-db");
33
+ const storage_migration_constants_1 = require("./storage-migration.constants");
34
+ const storage_migration_service_1 = require("./storage-migration.service");
35
+ /**
36
+ * Fails the run of a planner that gave up, and the item of an object job that gave up.
37
+ *
38
+ * @stability experimental
39
+ */
40
+ let StorageMigrationSettledListener = StorageMigrationSettledListener_1 = class StorageMigrationSettledListener {
41
+ migrations;
42
+ logger = new common_1.Logger(StorageMigrationSettledListener_1.name);
43
+ constructor(migrations) {
44
+ this.migrations = migrations;
45
+ }
46
+ /** Dispatches a failed migration job; ignores everything else. Never throws. */
47
+ async onJobSettled(event) {
48
+ if (event.succeeded || !event.subjectId)
49
+ return;
50
+ const message = (0, storage_migration_service_1.storageMigrationErrorText)(event.lastError ?? 'no error recorded');
51
+ try {
52
+ if (event.type === storage_migration_constants_1.STORAGE_MIGRATE_PLAN_TYPE && event.subjectType === storage_migration_constants_1.STORAGE_MIGRATION_RUN_SUBJECT_TYPE) {
53
+ await this.migrations.failRun(event.subjectId, `The planner failed: ${message}`);
54
+ return;
55
+ }
56
+ if (event.type !== storage_migration_constants_1.STORAGE_MIGRATE_OBJECT_TYPE || event.subjectType !== storage_migration_constants_1.STORAGE_MIGRATION_ITEM_SUBJECT_TYPE)
57
+ return;
58
+ await this.migrations.db().storageMigrationItem.updateMany({
59
+ where: {
60
+ id: event.subjectId,
61
+ status: { in: [storage_db_1.StorageMigrationItemStatus.pending, storage_db_1.StorageMigrationItemStatus.copying] },
62
+ },
63
+ data: { status: storage_db_1.StorageMigrationItemStatus.failed, lastError: message },
64
+ });
65
+ const runId = event.job.payload?.runId;
66
+ if (typeof runId === 'string') {
67
+ await this.migrations.recordRunError(runId, message);
68
+ await this.migrations.finalizeIfDone(runId);
69
+ }
70
+ }
71
+ catch (error) {
72
+ this.logger.error(`Could not record the failure of ${event.type} job ${event.jobId}: ${(0, storage_migration_service_1.storageMigrationErrorText)(error)}`);
73
+ }
74
+ }
75
+ };
76
+ exports.StorageMigrationSettledListener = StorageMigrationSettledListener;
77
+ __decorate([
78
+ (0, event_emitter_1.OnEvent)(index_1.JOB_SETTLED_EVENT),
79
+ __metadata("design:type", Function),
80
+ __metadata("design:paramtypes", [Function]),
81
+ __metadata("design:returntype", Promise)
82
+ ], StorageMigrationSettledListener.prototype, "onJobSettled", null);
83
+ exports.StorageMigrationSettledListener = StorageMigrationSettledListener = StorageMigrationSettledListener_1 = __decorate([
84
+ (0, common_1.Injectable)(),
85
+ __metadata("design:paramtypes", [storage_migration_service_1.StorageMigrationService])
86
+ ], StorageMigrationSettledListener);
87
+ //# sourceMappingURL=storage-migration-settled.listener.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-migration-settled.listener.js","sourceRoot":"","sources":["../../../src/storage/migration/storage-migration-settled.listener.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,8EAA8E;AAC9E,gBAAgB;AAChB,gFAAgF;AAChF,EAAE;AACF,8EAA8E;AAC9E,4EAA4E;AAC5E,+EAA+E;AAC/E,yDAAyD;AACzD,EAAE;AACF,+EAA+E;AAC/E,iCAAiC;AACjC,gFAAgF;AAChF,8EAA8E;AAC9E,gFAAgF;;;;;;;;;;;;;AAEhF,2CAAoD;AACpD,yDAAgD;AAEhD,4CAA2E;AAC3E,mDAAgE;AAChE,+EAKuC;AACvC,2EAAiG;AAEjG;;;;GAIG;AAEI,IAAM,+BAA+B,uCAArC,MAAM,+BAA+B;IAGb;IAFZ,MAAM,GAAG,IAAI,eAAM,CAAC,iCAA+B,CAAC,IAAI,CAAC,CAAC;IAE3E,YAA6B,UAAmC;QAAnC,eAAU,GAAV,UAAU,CAAyB;IAAG,CAAC;IAEpE,gFAAgF;IAE1E,AAAN,KAAK,CAAC,YAAY,CAAC,KAAsB;QACvC,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,SAAS;YAAE,OAAO;QAChD,MAAM,OAAO,GAAG,IAAA,qDAAyB,EAAC,KAAK,CAAC,SAAS,IAAI,mBAAmB,CAAC,CAAC;QAElF,IAAI,CAAC;YACH,IAAI,KAAK,CAAC,IAAI,KAAK,uDAAyB,IAAI,KAAK,CAAC,WAAW,KAAK,gEAAkC,EAAE,CAAC;gBACzG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,uBAAuB,OAAO,EAAE,CAAC,CAAC;gBACjF,OAAO;YACT,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,yDAA2B,IAAI,KAAK,CAAC,WAAW,KAAK,iEAAmC;gBAAE,OAAO;YAEpH,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,UAAU,CAAC;gBACzD,KAAK,EAAE;oBACL,EAAE,EAAE,KAAK,CAAC,SAAS;oBACnB,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,uCAA0B,CAAC,OAAO,EAAE,uCAA0B,CAAC,OAAO,CAAC,EAAE;iBACzF;gBACD,IAAI,EAAE,EAAE,MAAM,EAAE,uCAA0B,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE;aACxE,CAAC,CAAC;YACH,MAAM,KAAK,GAAI,KAAK,CAAC,GAAG,CAAC,OAAsC,EAAE,KAAK,CAAC;YACvE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC9B,MAAM,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBACrD,MAAM,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,mCAAmC,KAAK,CAAC,IAAI,QAAQ,KAAK,CAAC,KAAK,KAAK,IAAA,qDAAyB,EAAC,KAAK,CAAC,EAAE,CACxG,CAAC;QACJ,CAAC;IACH,CAAC;CACF,CAAA;AApCY,0EAA+B;AAOpC;IADL,IAAA,uBAAO,EAAC,yBAAiB,CAAC;;;;mEA6B1B;0CAnCU,+BAA+B;IAD3C,IAAA,mBAAU,GAAE;qCAI8B,mDAAuB;GAHrD,+BAA+B,CAoC3C"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * The job type that lists a run's objects, creates one item per object and
3
+ * queues one {@link STORAGE_MIGRATE_OBJECT_TYPE} job per item. PERMANENT:
4
+ * rows outlive handlers. Server-only (no `nodeResultSchema`).
5
+ *
6
+ * @stability experimental
7
+ */
8
+ export declare const STORAGE_MIGRATE_PLAN_TYPE = "storage.migrate_plan";
9
+ /**
10
+ * The job type that copies ONE object to the run's target driver, verifies it
11
+ * and repoints its row. PERMANENT. Server-only: it needs both drivers' secrets,
12
+ * which are never brokered to a worker node.
13
+ *
14
+ * @stability experimental
15
+ */
16
+ export declare const STORAGE_MIGRATE_OBJECT_TYPE = "storage.migrate_object";
17
+ /**
18
+ * The `subjectType` of a planner job (`subjectId` is the run id).
19
+ *
20
+ * @stability experimental
21
+ */
22
+ export declare const STORAGE_MIGRATION_RUN_SUBJECT_TYPE = "storage_migration_run";
23
+ /**
24
+ * The `subjectType` of a per-object job (`subjectId` is the item id).
25
+ *
26
+ * @stability experimental
27
+ */
28
+ export declare const STORAGE_MIGRATION_ITEM_SUBJECT_TYPE = "storage_migration_item";
29
+ /**
30
+ * The queue priority of both job types: background, the housekeeping value,
31
+ * so a migration never delays an upload's processing.
32
+ *
33
+ * @stability experimental
34
+ */
35
+ export declare const STORAGE_MIGRATION_PRIORITY: number;
36
+ /**
37
+ * The raw-SQL partial unique index that allows one pending or running run.
38
+ *
39
+ * @stability experimental
40
+ */
41
+ export declare const STORAGE_MIGRATION_ACTIVE_INDEX = "storage_migration_runs_active_uniq_idx";
42
+ /**
43
+ * The system access reason every migration query names: a run is
44
+ * deployment-wide (its `org_id` is NULL) and spans every organization's objects.
45
+ *
46
+ * @stability experimental
47
+ */
48
+ export declare const STORAGE_MIGRATION_SYSTEM_ACCESS_REASON = "storage-migration";
49
+ /**
50
+ * The audit actions the migration writes.
51
+ *
52
+ * @stability experimental
53
+ */
54
+ export declare const STORAGE_MIGRATION_AUDIT_ACTIONS: {
55
+ /** A run was started. */
56
+ readonly START: 'storage.migration.start';
57
+ /** A run was cancelled. */
58
+ readonly CANCEL: 'storage.migration.cancel';
59
+ };
60
+ /**
61
+ * Registers {@link STORAGE_MIGRATION_SYSTEM_ACCESS_REASON} with core's
62
+ * registry, once. The service and both handlers call it from their
63
+ * constructors (bootstrap, before the registry freezes), so code that builds
64
+ * them by hand (a database test) is covered too.
65
+ *
66
+ * @stability experimental
67
+ */
68
+ export declare function registerStorageMigrationSystemAccessReason(): void;
69
+ //# sourceMappingURL=storage-migration.constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-migration.constants.d.ts","sourceRoot":"","sources":["../../../src/storage/migration/storage-migration.constants.ts"],"names":[],"mappings":"AAOA;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,yBAAyB,CAAC;AAEhE;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,2BAA2B,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,kCAAkC,0BAA0B,CAAC;AAE1E;;;;GAIG;AACH,eAAO,MAAM,mCAAmC,2BAA2B,CAAC;AAE5E;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAA8B,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,2CAA2C,CAAC;AAEvF;;;;;GAKG;AACH,eAAO,MAAM,sCAAsC,sBAAsB,CAAC;AAE1E;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,EAAE;IAC5C,yBAAyB;IACzB,QAAQ,CAAC,KAAK,EAAE,yBAAyB,CAAC;IAC1C,2BAA2B;IAC3B,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC;CAIpC,CAAC;AAEX;;;;;;;GAOG;AACH,wBAAgB,0CAA0C,IAAI,IAAI,CAOjE"}