@futo-org/backups-orchestrator-api 0.3.1 → 0.5.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.
Files changed (70) hide show
  1. package/dist/backends/backend.d.ts +2 -2
  2. package/dist/backends/backend.js +2 -5
  3. package/dist/backends/backend.js.map +1 -1
  4. package/dist/backends/local.backend.d.ts +1 -0
  5. package/dist/backends/local.backend.js +3 -0
  6. package/dist/backends/local.backend.js.map +1 -1
  7. package/dist/backends/s3.backend.d.ts +1 -0
  8. package/dist/backends/s3.backend.js +3 -0
  9. package/dist/backends/s3.backend.js.map +1 -1
  10. package/dist/backends/yucca.backend.d.ts +19 -3
  11. package/dist/backends/yucca.backend.js +47 -22
  12. package/dist/backends/yucca.backend.js.map +1 -1
  13. package/dist/const.d.ts +2 -1
  14. package/dist/const.js +3 -2
  15. package/dist/const.js.map +1 -1
  16. package/dist/controllers/onboarding.controller.d.ts +2 -0
  17. package/dist/controllers/onboarding.controller.js +18 -0
  18. package/dist/controllers/onboarding.controller.js.map +1 -1
  19. package/dist/dto/onboarding.dto.d.ts +4 -0
  20. package/dist/dto/onboarding.dto.js +16 -0
  21. package/dist/dto/onboarding.dto.js.map +1 -1
  22. package/dist/enum.d.ts +10 -0
  23. package/dist/enum.js +13 -1
  24. package/dist/enum.js.map +1 -1
  25. package/dist/interceptors/telemetry-error.interceptor.d.ts +8 -0
  26. package/dist/interceptors/telemetry-error.interceptor.js +47 -0
  27. package/dist/interceptors/telemetry-error.interceptor.js.map +1 -0
  28. package/dist/moduleConfig.d.ts +1 -1
  29. package/dist/orchestrationApi.module.d.ts +5 -3
  30. package/dist/orchestrationApi.module.js +13 -4
  31. package/dist/orchestrationApi.module.js.map +1 -1
  32. package/dist/repositories/backend.repository.d.ts +2 -0
  33. package/dist/repositories/backend.repository.js +8 -3
  34. package/dist/repositories/backend.repository.js.map +1 -1
  35. package/dist/repositories/bootstrap.repository.d.ts +9 -0
  36. package/dist/repositories/bootstrap.repository.js +33 -0
  37. package/dist/repositories/bootstrap.repository.js.map +1 -0
  38. package/dist/repositories/config.repository.d.ts +2 -0
  39. package/dist/repositories/config.repository.js +6 -0
  40. package/dist/repositories/config.repository.js.map +1 -1
  41. package/dist/repositories/restic.repository.d.ts +32 -3
  42. package/dist/repositories/restic.repository.js +3 -7
  43. package/dist/repositories/restic.repository.js.map +1 -1
  44. package/dist/schema/tables/backend.table.d.ts +1 -0
  45. package/dist/schema/tables/backend.table.js.map +1 -1
  46. package/dist/services/auth.service.d.ts +3 -1
  47. package/dist/services/auth.service.js +24 -7
  48. package/dist/services/auth.service.js.map +1 -1
  49. package/dist/services/backend.service.d.ts +3 -3
  50. package/dist/services/backend.service.js +12 -8
  51. package/dist/services/backend.service.js.map +1 -1
  52. package/dist/services/bootstrap.service.d.ts +3 -1
  53. package/dist/services/bootstrap.service.js +16 -6
  54. package/dist/services/bootstrap.service.js.map +1 -1
  55. package/dist/services/integrations.service.d.ts +3 -1
  56. package/dist/services/integrations.service.js +10 -2
  57. package/dist/services/integrations.service.js.map +1 -1
  58. package/dist/services/onboarding.service.d.ts +7 -1
  59. package/dist/services/onboarding.service.js +37 -2
  60. package/dist/services/onboarding.service.js.map +1 -1
  61. package/dist/services/repository.service.d.ts +3 -1
  62. package/dist/services/repository.service.js +188 -76
  63. package/dist/services/repository.service.js.map +1 -1
  64. package/dist/services/schedule.service.d.ts +3 -1
  65. package/dist/services/schedule.service.js +26 -2
  66. package/dist/services/schedule.service.js.map +1 -1
  67. package/dist/services/telemetry.service.d.ts +9 -0
  68. package/dist/services/telemetry.service.js +59 -0
  69. package/dist/services/telemetry.service.js.map +1 -0
  70. package/package.json +5 -4
@@ -1,17 +1,23 @@
1
1
  import { CurrentRecoveryKeyResponse, OnboardingStatusResponseDto } from '../dto/onboarding.dto';
2
2
  import { BackendRepository } from '../repositories/backend.repository';
3
+ import { BootstrapRepository } from '../repositories/bootstrap.repository';
3
4
  import { ConfigRepository } from '../repositories/config.repository';
4
5
  import { RepositoryRepository } from '../repositories/repository.repository';
5
6
  import { ScheduleRepository } from '../repositories/schedule.repository';
7
+ import { TelemetryService } from './telemetry.service';
6
8
  export declare class OnboardingService {
7
9
  private readonly backend;
8
10
  private readonly repository;
9
11
  private readonly schedule;
10
12
  private readonly config;
11
- constructor(backend: BackendRepository, repository: RepositoryRepository, schedule: ScheduleRepository, config: ConfigRepository);
13
+ private readonly bootstrap;
14
+ private readonly telemetry;
15
+ constructor(backend: BackendRepository, repository: RepositoryRepository, schedule: ScheduleRepository, config: ConfigRepository, bootstrap: BootstrapRepository, telemetry: TelemetryService);
12
16
  onboardingStatus(): Promise<OnboardingStatusResponseDto>;
13
17
  currentRecoveryKey(): Promise<CurrentRecoveryKeyResponse>;
14
18
  importRecoveryKey(key: string): Promise<void>;
15
19
  confirmRecoveryKey(): Promise<void>;
16
20
  skipExtraConfig(): Promise<void>;
21
+ enableTelemetry(): Promise<void>;
22
+ reportError(): void;
17
23
  }
@@ -11,26 +11,50 @@ var __metadata = (this && this.__metadata) || function (k, v) {
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.OnboardingService = void 0;
13
13
  const common_1 = require("@nestjs/common");
14
+ const enum_1 = require("../enum");
14
15
  const backend_repository_1 = require("../repositories/backend.repository");
16
+ const bootstrap_repository_1 = require("../repositories/bootstrap.repository");
15
17
  const config_repository_1 = require("../repositories/config.repository");
16
18
  const repository_repository_1 = require("../repositories/repository.repository");
17
19
  const schedule_repository_1 = require("../repositories/schedule.repository");
20
+ const telemetry_service_1 = require("./telemetry.service");
18
21
  let OnboardingService = class OnboardingService {
19
22
  backend;
20
23
  repository;
21
24
  schedule;
22
25
  config;
23
- constructor(backend, repository, schedule, config) {
26
+ bootstrap;
27
+ telemetry;
28
+ constructor(backend, repository, schedule, config, bootstrap, telemetry) {
24
29
  this.backend = backend;
25
30
  this.repository = repository;
26
31
  this.schedule = schedule;
27
32
  this.config = config;
33
+ this.bootstrap = bootstrap;
34
+ this.telemetry = telemetry;
28
35
  }
29
36
  async onboardingStatus() {
37
+ const status = this.bootstrap.getStatus();
38
+ if (status !== enum_1.BootstrapStatus.Ready) {
39
+ let error = this.bootstrap.getError();
40
+ error = error ? `${error}` : undefined;
41
+ return {
42
+ status,
43
+ error,
44
+ hasTelemetry: enum_1.TelemetryLevel.None,
45
+ hasOnboardedKey: false,
46
+ hasBackend: false,
47
+ hasBackup: false,
48
+ hasSchedule: false,
49
+ hasSkippedExtraConfig: false,
50
+ };
51
+ }
30
52
  const backends = await this.backend.getBackends();
31
53
  const repositories = await this.repository.getAll();
32
54
  const schedules = await this.schedule.getAll();
33
55
  return {
56
+ status: enum_1.BootstrapStatus.Ready,
57
+ hasTelemetry: (await this.config.hasTelemetry()) ? enum_1.TelemetryLevel.Full : enum_1.TelemetryLevel.None,
34
58
  hasOnboardedKey: await this.config.hasOnboardedKey(),
35
59
  hasBackend: backends.length > 0,
36
60
  hasBackup: repositories.length > 0,
@@ -53,6 +77,15 @@ let OnboardingService = class OnboardingService {
53
77
  async skipExtraConfig() {
54
78
  await this.config.skipExtraConfig();
55
79
  }
80
+ async enableTelemetry() {
81
+ await this.config.enableTelemetry();
82
+ this.telemetry.submitStructuredLog('Telemetry consent granted', {});
83
+ }
84
+ reportError() {
85
+ this.telemetry.submitStructuredLog('Bootstrap error', {
86
+ error: this.bootstrap.getError(),
87
+ }, true);
88
+ }
56
89
  };
57
90
  exports.OnboardingService = OnboardingService;
58
91
  exports.OnboardingService = OnboardingService = __decorate([
@@ -60,6 +93,8 @@ exports.OnboardingService = OnboardingService = __decorate([
60
93
  __metadata("design:paramtypes", [backend_repository_1.BackendRepository,
61
94
  repository_repository_1.RepositoryRepository,
62
95
  schedule_repository_1.ScheduleRepository,
63
- config_repository_1.ConfigRepository])
96
+ config_repository_1.ConfigRepository,
97
+ bootstrap_repository_1.BootstrapRepository,
98
+ telemetry_service_1.TelemetryService])
64
99
  ], OnboardingService);
65
100
  //# sourceMappingURL=onboarding.service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"onboarding.service.js","sourceRoot":"","sources":["../../src/services/onboarding.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAE5C,2EAAuE;AACvE,yEAAqE;AACrE,iFAA6E;AAC7E,6EAAyE;AAGlE,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAET;IACA;IACA;IACA;IAJnB,YACmB,OAA0B,EAC1B,UAAgC,EAChC,QAA4B,EAC5B,MAAwB;QAHxB,YAAO,GAAP,OAAO,CAAmB;QAC1B,eAAU,GAAV,UAAU,CAAsB;QAChC,aAAQ,GAAR,QAAQ,CAAoB;QAC5B,WAAM,GAAN,MAAM,CAAkB;IACxC,CAAC;IAEJ,KAAK,CAAC,gBAAgB;QACpB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QAClD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QACpD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QAE/C,OAAO;YACL,eAAe,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE;YACpD,UAAU,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC;YAC/B,SAAS,EAAE,YAAY,CAAC,MAAM,GAAG,CAAC;YAClC,WAAW,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC;YACjC,qBAAqB,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,qBAAqB,EAAE;SACjE,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAAE,CAAC;QAE/D,OAAO;YACL,WAAW;SACZ,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,GAAW;QACjC,MAAM,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,MAAM,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,MAAM,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;IACtC,CAAC;CACF,CAAA;AAzCY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,mBAAU,GAAE;qCAGiB,sCAAiB;QACd,4CAAoB;QACtB,wCAAkB;QACpB,oCAAgB;GALhC,iBAAiB,CAyC7B"}
1
+ {"version":3,"file":"onboarding.service.js","sourceRoot":"","sources":["../../src/services/onboarding.service.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@ import { RunHistoryRepository } from '../repositories/runHistory.repository';
14
14
  import { RunningTasksRepository } from '../repositories/runningTasks.repository';
15
15
  import { StorageRepository } from '../repositories/storage.repository';
16
16
  import { BootstrapService } from './bootstrap.service';
17
+ import { TelemetryService } from './telemetry.service';
17
18
  export declare class RepositoryService {
18
19
  private readonly tasks;
19
20
  private readonly events;
@@ -28,7 +29,8 @@ export declare class RepositoryService {
28
29
  private readonly moduleConfig;
29
30
  private readonly storage;
30
31
  private readonly bootstrap;
31
- constructor(tasks: RunningTasksRepository, events: EventsGateway, backend: BackendRepository, config: ConfigRepository, database: DatabaseRepository, restic: ResticRepository, runHistory: RunHistoryRepository, repository: RepositoryRepository, repositoryPath: RepositoryPathRepository, repositoryLocalMetrics: RepositoryLocalMetricsRepository, moduleConfig: ModuleConfigRepository, storage: StorageRepository, bootstrap: BootstrapService);
32
+ private readonly telemetry;
33
+ constructor(tasks: RunningTasksRepository, events: EventsGateway, backend: BackendRepository, config: ConfigRepository, database: DatabaseRepository, restic: ResticRepository, runHistory: RunHistoryRepository, repository: RepositoryRepository, repositoryPath: RepositoryPathRepository, repositoryLocalMetrics: RepositoryLocalMetricsRepository, moduleConfig: ModuleConfigRepository, storage: StorageRepository, bootstrap: BootstrapService, telemetry: TelemetryService);
32
34
  private getLocalRepository;
33
35
  createRepository(dto: RepositoryCreateRequestDto, backendId?: string): Promise<RepositoryCreateResponseDto>;
34
36
  getRepositories(): Promise<RepositoryListResponseDto>;
@@ -16,7 +16,6 @@ exports.RepositoryService = void 0;
16
16
  const common_1 = require("@nestjs/common");
17
17
  const node_crypto_1 = require("node:crypto");
18
18
  const node_path_1 = require("node:path");
19
- const backend_1 = require("../backends/backend");
20
19
  const enum_1 = require("../enum");
21
20
  const events_gateway_1 = require("../events/events.gateway");
22
21
  const backend_repository_1 = require("../repositories/backend.repository");
@@ -32,6 +31,7 @@ const runningTasks_repository_1 = require("../repositories/runningTasks.reposito
32
31
  const storage_repository_1 = require("../repositories/storage.repository");
33
32
  const restic_1 = require("../utils/restic");
34
33
  const bootstrap_service_1 = require("./bootstrap.service");
34
+ const telemetry_service_1 = require("./telemetry.service");
35
35
  let RepositoryService = class RepositoryService {
36
36
  tasks;
37
37
  events;
@@ -46,7 +46,8 @@ let RepositoryService = class RepositoryService {
46
46
  moduleConfig;
47
47
  storage;
48
48
  bootstrap;
49
- constructor(tasks, events, backend, config, database, restic, runHistory, repository, repositoryPath, repositoryLocalMetrics, moduleConfig, storage, bootstrap) {
49
+ telemetry;
50
+ constructor(tasks, events, backend, config, database, restic, runHistory, repository, repositoryPath, repositoryLocalMetrics, moduleConfig, storage, bootstrap, telemetry) {
50
51
  this.tasks = tasks;
51
52
  this.events = events;
52
53
  this.backend = backend;
@@ -60,6 +61,7 @@ let RepositoryService = class RepositoryService {
60
61
  this.moduleConfig = moduleConfig;
61
62
  this.storage = storage;
62
63
  this.bootstrap = bootstrap;
64
+ this.telemetry = telemetry;
63
65
  }
64
66
  async getLocalRepository(id, configuration, metrics) {
65
67
  if (!configuration) {
@@ -77,8 +79,7 @@ let RepositoryService = class RepositoryService {
77
79
  const backends = await this.backend.getBackends();
78
80
  backendId = backends[0].id;
79
81
  }
80
- const { configuration } = await this.backend.getBackend(backendId);
81
- const backend = backend_1.Backend.from(configuration, this.moduleConfig.get());
82
+ const { backend, configuration } = await this.backend.getBackend(backendId);
82
83
  const { repository: remote } = await backend.createRepository(dto);
83
84
  const id = (0, node_crypto_1.randomUUID)();
84
85
  const endpoint = await backend.getResticEndpoint(remote.id);
@@ -107,6 +108,10 @@ let RepositoryService = class RepositoryService {
107
108
  secondary: [],
108
109
  },
109
110
  };
111
+ this.telemetry.submitStructuredLog('Created repository', {
112
+ repositoryId: remote.id,
113
+ backendId,
114
+ });
110
115
  this.events.publish({
111
116
  type: 'RepositoryCreate',
112
117
  repository,
@@ -120,8 +125,7 @@ let RepositoryService = class RepositoryService {
120
125
  const repositories = [];
121
126
  const backendsById = Object.fromEntries(backends.map((backend) => [backend.id, backend]));
122
127
  const remoteRepositories = {};
123
- for (const { id: backendId, configuration } of backends) {
124
- const backend = backend_1.Backend.from(configuration, this.moduleConfig.get());
128
+ for (const { id: backendId, backend } of backends) {
125
129
  remoteRepositories[backendId] = {};
126
130
  try {
127
131
  const { repositories: list } = await backend.getRepositories();
@@ -242,14 +246,13 @@ let RepositoryService = class RepositoryService {
242
246
  backendId = localRepository.backendId;
243
247
  remoteId = localRepository.remoteId;
244
248
  }
245
- const backend = await this.backend.getBackend(backendId);
246
- const backendInstance = backend_1.Backend.from(backend.configuration, this.moduleConfig.get());
249
+ const { backend, configuration } = await this.backend.getBackend(backendId);
247
250
  let remote;
248
251
  if (dto.name) {
249
- ({ repository: remote } = await backendInstance.updateRepository(remoteId, dto));
252
+ ({ repository: remote } = await backend.updateRepository(remoteId, dto));
250
253
  }
251
254
  else {
252
- ({ repository: remote } = await backendInstance.getRepository(remoteId));
255
+ ({ repository: remote } = await backend.getRepository(remoteId));
253
256
  }
254
257
  if (dto.paths) {
255
258
  const currentPaths = new Set(await this.repositoryPath.get(id));
@@ -277,12 +280,15 @@ let RepositoryService = class RepositoryService {
277
280
  backends: {
278
281
  primary: {
279
282
  id: backendId,
280
- type: backend.configuration.type,
283
+ type: configuration.type,
281
284
  online: true,
282
285
  },
283
286
  secondary: [],
284
287
  },
285
288
  };
289
+ this.telemetry.submitStructuredLog('Updated repository', {
290
+ repositoryId: id,
291
+ });
286
292
  this.events.publish({
287
293
  type: 'RepositoryUpdate',
288
294
  repositoryId: id,
@@ -294,6 +300,9 @@ let RepositoryService = class RepositoryService {
294
300
  }
295
301
  async deleteRepository(id) {
296
302
  await this.repository.delete(id);
303
+ this.telemetry.submitStructuredLog('Deleted repository', {
304
+ repositoryId: id,
305
+ });
297
306
  this.events.publish({
298
307
  type: 'RepositoryDelete',
299
308
  repositoryId: id,
@@ -313,9 +322,8 @@ let RepositoryService = class RepositoryService {
313
322
  else {
314
323
  ({ backendId, remoteId } = repository);
315
324
  }
316
- const backend = await this.backend.getBackend(backendId);
317
- const backendInstance = backend_1.Backend.from(backend.configuration, this.moduleConfig.get());
318
- const endpoint = await backendInstance.getResticEndpoint(remoteId);
325
+ const { backend } = await this.backend.getBackend(backendId);
326
+ const endpoint = await backend.getResticEndpoint(remoteId);
319
327
  const key = await this.config.deriveEncryptionKey(`repository-${remoteId}`);
320
328
  return { endpoint, key };
321
329
  }
@@ -339,23 +347,31 @@ let RepositoryService = class RepositoryService {
339
347
  });
340
348
  if (metrics.sizeBytes) {
341
349
  const { backendId, remoteId } = await this.repository.get(id);
342
- const { configuration } = await this.backend.getBackend(backendId);
343
- const backend = backend_1.Backend.from(configuration, this.moduleConfig.get());
350
+ const { backend } = await this.backend.getBackend(backendId);
344
351
  if (backend.isMetricsCapable()) {
345
352
  await backend.submitMetricRepositorySize(remoteId, metrics.sizeBytes);
346
353
  }
347
354
  }
348
355
  }
349
- catch {
356
+ catch (error) {
357
+ this.telemetry.submitStructuredLog('Failed to update repository metrics', {
358
+ repositoryId: id,
359
+ error,
360
+ });
350
361
  }
351
362
  }
352
363
  async createBackup(id, signal) {
353
364
  if (!this.tasks.canStart(id)) {
365
+ this.telemetry.submitStructuredLog('Backup rejected, task already running', {
366
+ repositoryId: id,
367
+ });
354
368
  throw new common_1.BadRequestException('Task already running!');
355
369
  }
370
+ this.telemetry.submitStructuredLog('Running backup', {
371
+ repositoryId: id,
372
+ });
356
373
  const { backendId, remoteId } = await this.repository.get(id);
357
- const { configuration } = await this.backend.getBackend(backendId);
358
- const backend = backend_1.Backend.from(configuration, this.moduleConfig.get());
374
+ const { backend } = await this.backend.getBackend(backendId);
359
375
  const { endpoint, key } = await this.getResticParameters(id);
360
376
  const paths = await this.repositoryPath.get(id);
361
377
  if (paths.length === 0) {
@@ -374,10 +390,17 @@ let RepositoryService = class RepositoryService {
374
390
  try {
375
391
  const taskSignal = this.tasks.startTask(id, enum_1.TaskType.Backup, logId, signal);
376
392
  await this.restic.unlockAll(endpoint, key);
377
- await this.restic.backup(endpoint, key, paths, log, taskSignal);
393
+ const summary = await this.restic.backup(endpoint, key, paths, log, taskSignal);
394
+ this.telemetry.submitStructuredLog('Finished backup to primary backend', {
395
+ repositoryId: id,
396
+ summary,
397
+ });
378
398
  const { retentionPolicy: policy } = await this.repository.get(id);
379
399
  if (policy) {
380
400
  await this.runForgetAndPrune(endpoint, key, policy, log, taskSignal);
401
+ this.telemetry.submitStructuredLog('Finished prune on primary backend', {
402
+ repositoryId: id,
403
+ });
381
404
  }
382
405
  }
383
406
  finally {
@@ -395,6 +418,10 @@ let RepositoryService = class RepositoryService {
395
418
  lastBackupDuration,
396
419
  },
397
420
  });
421
+ this.telemetry.submitStructuredLog('Backup finished', {
422
+ repositoryId: id,
423
+ error,
424
+ });
398
425
  if (error) {
399
426
  fail(error);
400
427
  }
@@ -431,12 +458,19 @@ let RepositoryService = class RepositoryService {
431
458
  }
432
459
  async pruneRepository(id, signal) {
433
460
  if (!this.tasks.canStart(id)) {
461
+ this.telemetry.submitStructuredLog('Repository prune rejected, task already running', {
462
+ repositoryId: id,
463
+ });
434
464
  throw new common_1.BadRequestException('Task already running!');
435
465
  }
436
466
  const { retentionPolicy: policy } = await this.repository.get(id);
437
467
  if (!policy) {
438
468
  throw new common_1.BadRequestException('No retention policy configured for this repository');
439
469
  }
470
+ this.telemetry.submitStructuredLog('Running repository prune', {
471
+ repositoryId: id,
472
+ retentionPolicy: policy,
473
+ });
440
474
  const { endpoint, key } = await this.getResticParameters(id);
441
475
  return new Promise((resolve) => {
442
476
  const task = new Promise((complete, fail) => void this.runHistory.createLog(id, enum_1.TaskType.Forget, async (log, logId) => {
@@ -453,6 +487,10 @@ let RepositoryService = class RepositoryService {
453
487
  void this.updateLocalMetrics(id, {
454
488
  resticParameters: { endpoint, key },
455
489
  });
490
+ this.telemetry.submitStructuredLog('Finished repository prune', {
491
+ repositoryId: id,
492
+ error,
493
+ });
456
494
  if (error) {
457
495
  fail(error);
458
496
  }
@@ -478,51 +516,72 @@ let RepositoryService = class RepositoryService {
478
516
  }
479
517
  }
480
518
  async importRepository(id, backendId) {
481
- const { configuration } = await this.backend.getBackend(backendId);
482
- const backend = backend_1.Backend.from(configuration, this.moduleConfig.get());
483
- const { repository: remote } = await backend.getRepository(id);
484
- const localId = (0, node_crypto_1.randomUUID)();
485
- const endpoint = await backend.getResticEndpoint(remote.id);
486
- const key = await this.config.deriveEncryptionKey(`repository-${remote.id}`);
487
- await this.restic.keyList(endpoint, key);
488
- let paths = [];
489
- try {
490
- const snapshots = await this.restic.snapshots(endpoint, key);
491
- snapshots.sort((a, b) => +b.time - +a.time);
492
- paths = snapshots[0].paths;
493
- }
494
- catch {
495
- }
496
- await this.repository.create({
497
- id: localId,
498
- remoteId: remote.id,
519
+ this.telemetry.submitStructuredLog('Running repository import', {
520
+ repositoryId: id,
499
521
  backendId,
500
- retentionPolicy: restic_1.DEFAULT_RETENTION_POLICY,
501
522
  });
502
- const repository = {
503
- ...(await this.getLocalRepository(localId, { paths, retentionPolicy: restic_1.DEFAULT_RETENTION_POLICY })),
504
- ...remote,
505
- id: localId,
506
- backends: {
507
- primary: {
508
- id: backendId,
509
- online: true,
510
- type: configuration.type,
523
+ try {
524
+ const { configuration, backend } = await this.backend.getBackend(backendId);
525
+ const { repository: remote } = await backend.getRepository(id);
526
+ const localId = (0, node_crypto_1.randomUUID)();
527
+ const endpoint = await backend.getResticEndpoint(remote.id);
528
+ const key = await this.config.deriveEncryptionKey(`repository-${remote.id}`);
529
+ await this.restic.keyList(endpoint, key);
530
+ let paths = [];
531
+ try {
532
+ const snapshots = await this.restic.snapshots(endpoint, key);
533
+ snapshots.sort((a, b) => +b.time - +a.time);
534
+ paths = snapshots[0].paths;
535
+ }
536
+ catch (error) {
537
+ this.telemetry.submitStructuredLog('Failed to infer backup paths during import', {
538
+ repositoryId: id,
539
+ backendId,
540
+ error,
541
+ });
542
+ }
543
+ await this.repository.create({
544
+ id: localId,
545
+ remoteId: remote.id,
546
+ backendId,
547
+ retentionPolicy: restic_1.DEFAULT_RETENTION_POLICY,
548
+ });
549
+ const repository = {
550
+ ...(await this.getLocalRepository(localId, { paths, retentionPolicy: restic_1.DEFAULT_RETENTION_POLICY })),
551
+ ...remote,
552
+ id: localId,
553
+ backends: {
554
+ primary: {
555
+ id: backendId,
556
+ online: true,
557
+ type: configuration.type,
558
+ },
559
+ secondary: [],
511
560
  },
512
- secondary: [],
513
- },
514
- };
515
- this.events.publish({
516
- type: 'RepositoryCreate',
517
- repository,
518
- });
519
- return {
520
- repository,
521
- };
561
+ };
562
+ this.telemetry.submitStructuredLog('Finished repository import', {
563
+ repositoryId: id,
564
+ backendId,
565
+ });
566
+ this.events.publish({
567
+ type: 'RepositoryCreate',
568
+ repository,
569
+ });
570
+ return {
571
+ repository,
572
+ };
573
+ }
574
+ catch (error) {
575
+ this.telemetry.submitStructuredLog('Finished repository import', {
576
+ repositoryId: id,
577
+ backendId,
578
+ error,
579
+ });
580
+ throw error;
581
+ }
522
582
  }
523
583
  async reconfigureRepositoryPrimaryBackend(id, dto) {
524
- const { configuration } = await this.backend.getBackend(dto.backendId);
525
- const backend = backend_1.Backend.from(configuration, this.moduleConfig.get());
584
+ const { backend, configuration } = await this.backend.getBackend(dto.backendId);
526
585
  const { repository: remote } = await backend.createRepository({
527
586
  name: 'Restored Repository',
528
587
  worm: false,
@@ -566,7 +625,12 @@ let RepositoryService = class RepositoryService {
566
625
  };
567
626
  }
568
627
  async restoreSnapshot(id, snapshotId, dto) {
628
+ this.telemetry.submitStructuredLog('Running repository snapshot restore', {
629
+ repositoryId: id,
630
+ snapshotId,
631
+ });
569
632
  return new Promise((resolve) => {
633
+ let summary;
570
634
  const task = new Promise((complete, fail) => void this.runHistory.createLog(id, enum_1.TaskType.Restore, async (log, logId) => {
571
635
  resolve({
572
636
  task,
@@ -575,12 +639,18 @@ let RepositoryService = class RepositoryService {
575
639
  const { endpoint, key } = await this.getResticParameters(id);
576
640
  try {
577
641
  const signal = this.tasks.startTask(id, enum_1.TaskType.Restore, logId);
578
- await this.restic.restore(endpoint, key, snapshotId, dto, log, signal);
642
+ summary = await this.restic.restore(endpoint, key, snapshotId, dto, log, signal);
579
643
  }
580
644
  finally {
581
645
  this.tasks.endTask(id);
582
646
  }
583
647
  }, (error) => {
648
+ this.telemetry.submitStructuredLog('Finished repository snapshot restore', {
649
+ repositoryId: id,
650
+ snapshotId,
651
+ summary,
652
+ error,
653
+ });
584
654
  if (error) {
585
655
  fail(error);
586
656
  }
@@ -592,7 +662,12 @@ let RepositoryService = class RepositoryService {
592
662
  });
593
663
  }
594
664
  async restoreFromPoint(id, snapshotId, backendId, dto) {
665
+ this.telemetry.submitStructuredLog('Running repository restore from point', {
666
+ repositoryId: id,
667
+ snapshotId,
668
+ });
595
669
  return new Promise((resolve) => {
670
+ let summary;
596
671
  const task = new Promise((complete, fail) => void this.runHistory.createEphemeralLog(async (log, logId) => {
597
672
  resolve({
598
673
  task,
@@ -601,7 +676,7 @@ let RepositoryService = class RepositoryService {
601
676
  const { endpoint, key } = await this.getResticParameters({ backendId, remoteId: id });
602
677
  try {
603
678
  const signal = this.tasks.startTask(id, enum_1.TaskType.Restore, logId);
604
- await this.restic.restore(endpoint, key, snapshotId, { include: dto.include }, log, signal);
679
+ summary = await this.restic.restore(endpoint, key, snapshotId, { include: dto.include }, log, signal);
605
680
  if (dto.yuccaConfig) {
606
681
  const target = await this.storage.tempdir();
607
682
  await this.restic.restore(endpoint, key, snapshotId, { include: [dto.yuccaConfig], target }, log, signal);
@@ -619,6 +694,12 @@ let RepositoryService = class RepositoryService {
619
694
  this.tasks.endTask(id);
620
695
  }
621
696
  }, (error) => {
697
+ this.telemetry.submitStructuredLog('Finished repository restore from point', {
698
+ repositoryId: id,
699
+ snapshotId,
700
+ summary,
701
+ error,
702
+ });
622
703
  if (error) {
623
704
  fail(error);
624
705
  }
@@ -631,36 +712,66 @@ let RepositoryService = class RepositoryService {
631
712
  }
632
713
  async forgetSnapshot(id, snapshotId) {
633
714
  if (!this.tasks.canStart(id)) {
715
+ this.telemetry.submitStructuredLog('Repository snapshot forget rejected, task already running', {
716
+ repositoryId: id,
717
+ snapshotId,
718
+ });
634
719
  throw new common_1.BadRequestException('Task already running!');
635
720
  }
721
+ this.telemetry.submitStructuredLog('Running repository snapshot forget', {
722
+ repositoryId: id,
723
+ snapshotId,
724
+ });
636
725
  const { endpoint, key } = await this.getResticParameters(id);
726
+ let error;
637
727
  try {
638
728
  const signal = this.tasks.startTask(id, enum_1.TaskType.Forget);
639
729
  await this.restic.unlockAll(endpoint, key);
640
730
  await this.restic.forget(endpoint, key, snapshotId, true, signal);
641
731
  }
732
+ catch (error_) {
733
+ error = error_;
734
+ }
642
735
  finally {
643
736
  this.tasks.endTask(id);
644
737
  }
738
+ this.telemetry.submitStructuredLog('Finished repository snapshot forget', {
739
+ repositoryId: id,
740
+ snapshotId,
741
+ error,
742
+ });
743
+ if (error) {
744
+ throw error;
745
+ }
645
746
  await this.updateLocalMetrics(id, {
646
747
  resticParameters: { endpoint, key },
647
748
  });
648
749
  }
649
750
  async getSnapshotListing(id, snapshotId, dto) {
650
751
  const path = dto.path ?? '/';
651
- const { endpoint, key } = await this.getResticParameters(id);
652
- const files = await this.restic.ls(endpoint, key, snapshotId, path);
653
- return {
654
- parent: (0, node_path_1.dirname)(path),
655
- path,
656
- items: files
657
- .filter((file) => file.message_type === 'node')
658
- .filter((file) => file.path !== path)
659
- .map((file) => ({
660
- path: file.path,
661
- isDirectory: file.type === 'dir',
662
- })),
663
- };
752
+ try {
753
+ const { endpoint, key } = await this.getResticParameters(id);
754
+ const files = await this.restic.ls(endpoint, key, snapshotId, path);
755
+ return {
756
+ parent: (0, node_path_1.dirname)(path),
757
+ path,
758
+ items: files
759
+ .filter((file) => file.message_type === 'node')
760
+ .filter((file) => file.path !== path)
761
+ .map((file) => ({
762
+ path: file.path,
763
+ isDirectory: file.type === 'dir',
764
+ })),
765
+ };
766
+ }
767
+ catch (error) {
768
+ this.telemetry.submitStructuredLog('Failed to get repository snapshot listing', {
769
+ repositoryId: id,
770
+ snapshotId,
771
+ error,
772
+ });
773
+ throw error;
774
+ }
664
775
  }
665
776
  async getRunHistory(id) {
666
777
  const runs = await this.runHistory.getAll(id);
@@ -688,6 +799,7 @@ exports.RepositoryService = RepositoryService = __decorate([
688
799
  repositoryLocalMetrics_repository_1.RepositoryLocalMetricsRepository,
689
800
  moduleConfig_repository_1.ModuleConfigRepository,
690
801
  storage_repository_1.StorageRepository,
691
- bootstrap_service_1.BootstrapService])
802
+ bootstrap_service_1.BootstrapService,
803
+ telemetry_service_1.TelemetryService])
692
804
  ], RepositoryService);
693
805
  //# sourceMappingURL=repository.service.js.map