@causa/runtime-google 0.38.0 → 0.39.1

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.
@@ -11,22 +11,11 @@ import type { EventAttributes, OutboxEvent } from '@causa/runtime';
11
11
  * data BYTES(MAX) NOT NULL,
12
12
  * attributes JSON NOT NULL,
13
13
  * leaseExpiration TIMESTAMP,
14
- * publishedAt TIMESTAMP,
15
14
  * -- 20 is the number of shards.
16
15
  * shard INT64 AS (MOD(ABS(FARM_FINGERPRINT(id)), 20)),
17
- * ) PRIMARY KEY (id)
18
- * ROW DELETION POLICY (OLDER_THAN(publishedAt, INTERVAL 0 DAY));
19
- * CREATE INDEX OutboxEventsByShardAndLeaseExpiration ON OutboxEvent(shard, leaseExpiration) STORING (publishedAt);
16
+ * ) PRIMARY KEY (id);
17
+ * CREATE INDEX OutboxEventsByShardAndLeaseExpiration ON OutboxEvent(shard, leaseExpiration)
20
18
  * ```
21
- *
22
- * Compared to the {@link OutboxEvent} interface, this requires a `publishedAt` column to be defined, on which the row
23
- * deletion policy should be set. This allows updating published events rather than deleting them directly.
24
- * Updating published events allows setting the `leaseExpiration` column to a distant date, such that those events are
25
- * not scanned when fetching events to publish.
26
- * Because Spanner allows for version retention, recently deleted rows are still scanned (even as part of an efficient
27
- * index scan). This can affect performances if the rows are not updated before being deleted, because the
28
- * `leaseExpiration` date of published events would end up back in the scanned range - in the past (although rows are
29
- * deleted and not returned).
30
19
  */
31
20
  export declare class SpannerOutboxEvent implements OutboxEvent {
32
21
  constructor(init: SpannerOutboxEvent);
@@ -35,8 +24,4 @@ export declare class SpannerOutboxEvent implements OutboxEvent {
35
24
  readonly data: Buffer;
36
25
  readonly attributes: EventAttributes;
37
26
  readonly leaseExpiration: Date | null;
38
- /**
39
- * The date at which the event was successfully published.
40
- */
41
- readonly publishedAt: Date | null;
42
27
  }
@@ -20,22 +20,11 @@ import { SpannerColumn, SpannerTable } from '../../spanner/index.js';
20
20
  * data BYTES(MAX) NOT NULL,
21
21
  * attributes JSON NOT NULL,
22
22
  * leaseExpiration TIMESTAMP,
23
- * publishedAt TIMESTAMP,
24
23
  * -- 20 is the number of shards.
25
24
  * shard INT64 AS (MOD(ABS(FARM_FINGERPRINT(id)), 20)),
26
- * ) PRIMARY KEY (id)
27
- * ROW DELETION POLICY (OLDER_THAN(publishedAt, INTERVAL 0 DAY));
28
- * CREATE INDEX OutboxEventsByShardAndLeaseExpiration ON OutboxEvent(shard, leaseExpiration) STORING (publishedAt);
25
+ * ) PRIMARY KEY (id);
26
+ * CREATE INDEX OutboxEventsByShardAndLeaseExpiration ON OutboxEvent(shard, leaseExpiration)
29
27
  * ```
30
- *
31
- * Compared to the {@link OutboxEvent} interface, this requires a `publishedAt` column to be defined, on which the row
32
- * deletion policy should be set. This allows updating published events rather than deleting them directly.
33
- * Updating published events allows setting the `leaseExpiration` column to a distant date, such that those events are
34
- * not scanned when fetching events to publish.
35
- * Because Spanner allows for version retention, recently deleted rows are still scanned (even as part of an efficient
36
- * index scan). This can affect performances if the rows are not updated before being deleted, because the
37
- * `leaseExpiration` date of published events would end up back in the scanned range - in the past (although rows are
38
- * deleted and not returned).
39
28
  */
40
29
  let SpannerOutboxEvent = class SpannerOutboxEvent {
41
30
  constructor(init) {
@@ -46,10 +35,6 @@ let SpannerOutboxEvent = class SpannerOutboxEvent {
46
35
  data;
47
36
  attributes;
48
37
  leaseExpiration;
49
- /**
50
- * The date at which the event was successfully published.
51
- */
52
- publishedAt;
53
38
  };
54
39
  __decorate([
55
40
  SpannerColumn(),
@@ -71,10 +56,6 @@ __decorate([
71
56
  SpannerColumn(),
72
57
  __metadata("design:type", Object)
73
58
  ], SpannerOutboxEvent.prototype, "leaseExpiration", void 0);
74
- __decorate([
75
- SpannerColumn(),
76
- __metadata("design:type", Object)
77
- ], SpannerOutboxEvent.prototype, "publishedAt", void 0);
78
59
  SpannerOutboxEvent = __decorate([
79
60
  SpannerTable({ name: 'OutboxEvent', primaryKey: ['id'] }),
80
61
  __metadata("design:paramtypes", [SpannerOutboxEvent])
@@ -1,5 +1,5 @@
1
+ import type { OutboxEvent } from '@causa/runtime';
1
2
  import type { DynamicModule, Type } from '@nestjs/common';
2
- import { SpannerOutboxEvent } from './event.js';
3
3
  import { type SpannerOutboxSenderOptions } from './sender.js';
4
4
  /**
5
5
  * Options for the {@link SpannerOutboxTransactionModule}.
@@ -10,7 +10,7 @@ export type SpannerOutboxTransactionModuleOptions = SpannerOutboxSenderOptions &
10
10
  * This should be a valid class decorated with `@SpannerTable`.
11
11
  * Defaults to {@link SpannerOutboxEvent}.
12
12
  */
13
- outboxEventType?: Type<SpannerOutboxEvent>;
13
+ outboxEventType?: Type<OutboxEvent>;
14
14
  };
15
15
  /**
16
16
  * The module providing the {@link SpannerOutboxTransactionRunner}.
@@ -29,7 +29,6 @@ function parseSenderOptions(defaultOptions, customOptions, config) {
29
29
  const pollingInterval = validateIntOrUndefined('SPANNER_OUTBOX_POLLING_INTERVAL');
30
30
  const idColumn = config.get('SPANNER_OUTBOX_ID_COLUMN');
31
31
  const leaseExpirationColumn = config.get('SPANNER_OUTBOX_LEASE_EXPIRATION_COLUMN');
32
- const publishedAtColumn = config.get('SPANNER_OUTBOX_PUBLISHED_AT_COLUMN');
33
32
  const index = config.get('SPANNER_OUTBOX_INDEX');
34
33
  const shardingColumn = config.get('SPANNER_OUTBOX_SHARDING_COLUMN');
35
34
  const shardingCount = validateIntOrUndefined('SPANNER_OUTBOX_SHARDING_COUNT');
@@ -42,7 +41,6 @@ function parseSenderOptions(defaultOptions, customOptions, config) {
42
41
  pollingInterval,
43
42
  idColumn,
44
43
  leaseExpirationColumn,
45
- publishedAtColumn,
46
44
  index,
47
45
  sharding,
48
46
  leaseDuration,
@@ -1,9 +1,8 @@
1
- import { OutboxTransactionRunner, type OutboxEventTransaction } from '@causa/runtime';
1
+ import { OutboxTransactionRunner, type OutboxEvent, type OutboxEventTransaction } from '@causa/runtime';
2
2
  import { Logger } from '@causa/runtime/nestjs';
3
3
  import type { Type } from '@nestjs/common';
4
4
  import { SpannerEntityManager } from '../../spanner/index.js';
5
5
  import { SpannerTransaction } from '../spanner-transaction.js';
6
- import type { SpannerOutboxEvent } from './event.js';
7
6
  import { SpannerOutboxSender } from './sender.js';
8
7
  /**
9
8
  * A {@link SpannerTransaction} that uses an {@link OutboxEventTransaction}.
@@ -24,6 +23,6 @@ export type SpannerOutboxTransactionOption = {
24
23
  */
25
24
  export declare class SpannerOutboxTransactionRunner extends OutboxTransactionRunner<SpannerOutboxTransaction> {
26
25
  readonly entityManager: SpannerEntityManager;
27
- constructor(entityManager: SpannerEntityManager, outboxEventType: Type<SpannerOutboxEvent>, sender: SpannerOutboxSender, logger: Logger);
26
+ constructor(entityManager: SpannerEntityManager, outboxEventType: Type<OutboxEvent>, sender: SpannerOutboxSender, logger: Logger);
28
27
  protected runStateTransaction<RT>(eventTransactionFactory: () => OutboxEventTransaction, runFn: (transaction: SpannerOutboxTransaction) => Promise<RT>): Promise<RT>;
29
28
  }
@@ -34,11 +34,6 @@ export type SpannerOutboxSenderOptions = OutboxEventSenderOptions & {
34
34
  * Defaults to `leaseExpiration`.
35
35
  */
36
36
  readonly leaseExpirationColumn?: string;
37
- /**
38
- * The name of the column used to store the timestamp at which the event was published.
39
- * Defaults to `publishedAt`.
40
- */
41
- readonly publishedAtColumn?: string;
42
37
  /**
43
38
  * The index used to fetch events.
44
39
  */
@@ -63,10 +58,6 @@ export declare class SpannerOutboxSender extends OutboxEventSender {
63
58
  * The name of the column used for the {@link OutboxEvent.leaseExpiration} property.
64
59
  */
65
60
  readonly leaseExpirationColumn: string;
66
- /**
67
- * The name of the column used for the {@link OutboxEvent.publishedAt} property.
68
- */
69
- readonly publishedAtColumn: string;
70
61
  /**
71
62
  * The index used to fetch events.
72
63
  */
@@ -9,10 +9,6 @@ const DEFAULT_ID_COLUMN = 'id';
9
9
  * The default name for the {@link OutboxEvent.leaseExpiration} column.
10
10
  */
11
11
  const DEFAULT_LEASE_EXPIRATION_COLUMN = 'leaseExpiration';
12
- /**
13
- * The default name for the {@link OutboxEvent.publishedAt} column.
14
- */
15
- const DEFAULT_PUBLISHED_AT_COLUMN = 'publishedAt';
16
12
  /**
17
13
  * An {@link OutboxEventSender} that uses a Spanner table to store events.
18
14
  */
@@ -32,10 +28,6 @@ export class SpannerOutboxSender extends OutboxEventSender {
32
28
  * The name of the column used for the {@link OutboxEvent.leaseExpiration} property.
33
29
  */
34
30
  leaseExpirationColumn;
35
- /**
36
- * The name of the column used for the {@link OutboxEvent.publishedAt} property.
37
- */
38
- publishedAtColumn;
39
31
  /**
40
32
  * The index used to fetch events.
41
33
  */
@@ -75,8 +67,6 @@ export class SpannerOutboxSender extends OutboxEventSender {
75
67
  this.idColumn = options.idColumn ?? DEFAULT_ID_COLUMN;
76
68
  this.leaseExpirationColumn =
77
69
  options.leaseExpirationColumn ?? DEFAULT_LEASE_EXPIRATION_COLUMN;
78
- this.publishedAtColumn =
79
- options.publishedAtColumn ?? DEFAULT_PUBLISHED_AT_COLUMN;
80
70
  this.index = options.index;
81
71
  ({
82
72
  fetchEventsSql: this.fetchEventsSql,
@@ -93,11 +83,7 @@ export class SpannerOutboxSender extends OutboxEventSender {
93
83
  buildSql() {
94
84
  const table = this.entityManager.sqlTableName(this.outboxEventType);
95
85
  const tableWithIndex = this.entityManager.sqlTableName(this.outboxEventType, { index: this.index });
96
- const noLeaseFilter = `(
97
- \`${this.leaseExpirationColumn}\` IS NULL OR
98
- \`${this.leaseExpirationColumn}\` < @currentTime
99
- ) AND
100
- \`${this.publishedAtColumn}\` IS NULL`;
86
+ const noLeaseFilter = `\`${this.leaseExpirationColumn}\` IS NULL OR \`${this.leaseExpirationColumn}\` < @currentTime`;
101
87
  let fetchFilter = noLeaseFilter;
102
88
  if (this.sharding) {
103
89
  const { column, count } = this.sharding;
@@ -126,11 +112,8 @@ export class SpannerOutboxSender extends OutboxEventSender {
126
112
  THEN RETURN
127
113
  ${this.entityManager.sqlColumns(this.outboxEventType)}`;
128
114
  const successfulUpdateSql = `
129
- UPDATE
115
+ DELETE FROM
130
116
  ${table}
131
- SET
132
- \`${this.leaseExpirationColumn}\` = '9999-12-31T00:00:00.000Z',
133
- \`${this.publishedAtColumn}\` = @currentTime
134
117
  WHERE
135
118
  \`${this.idColumn}\` IN UNNEST(@ids)`;
136
119
  const failedUpdateSql = `
@@ -173,7 +156,7 @@ export class SpannerOutboxSender extends OutboxEventSender {
173
156
  if (successfulSends.length > 0) {
174
157
  batchUpdates.push({
175
158
  sql: this.successfulUpdateSql,
176
- params: { ids: successfulSends, currentTime: new Date() },
159
+ params: { ids: successfulSends },
177
160
  });
178
161
  }
179
162
  if (failedSends.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@causa/runtime-google",
3
- "version": "0.38.0",
3
+ "version": "0.39.1",
4
4
  "description": "An extension to the Causa runtime SDK (`@causa/runtime`), providing Google-specific features.",
5
5
  "repository": "github:causa-io/runtime-typescript-google",
6
6
  "license": "ISC",
@@ -29,20 +29,20 @@
29
29
  "test:cov": "npm run test -- --coverage"
30
30
  },
31
31
  "dependencies": {
32
- "@causa/runtime": ">= 0.27.0 < 1.0.0",
32
+ "@causa/runtime": ">= 0.27.1 < 1.0.0",
33
33
  "@google-cloud/precise-date": "^4.0.0",
34
34
  "@google-cloud/pubsub": "^4.10.0",
35
35
  "@google-cloud/spanner": "^7.18.1",
36
36
  "@google-cloud/tasks": "^5.5.2",
37
37
  "@grpc/grpc-js": "^1.12.6",
38
- "@nestjs/common": "^11.0.10",
39
- "@nestjs/config": "^4.0.0",
40
- "@nestjs/core": "^11.0.10",
38
+ "@nestjs/common": "^11.0.11",
39
+ "@nestjs/config": "^4.0.1",
40
+ "@nestjs/core": "^11.0.11",
41
41
  "@nestjs/passport": "^11.0.5",
42
42
  "@nestjs/terminus": "^11.0.0",
43
43
  "class-transformer": "^0.5.1",
44
44
  "class-validator": "^0.14.1",
45
- "express": "^4.21.2",
45
+ "express": "^5.0.1",
46
46
  "firebase-admin": "^13.1.0",
47
47
  "jsonwebtoken": "^9.0.2",
48
48
  "passport-http-bearer": "^1.0.1",
@@ -50,19 +50,19 @@
50
50
  "reflect-metadata": "^0.2.2"
51
51
  },
52
52
  "devDependencies": {
53
- "@nestjs/testing": "^11.0.10",
54
- "@swc/core": "^1.11.1",
53
+ "@nestjs/testing": "^11.0.11",
54
+ "@swc/core": "^1.11.7",
55
55
  "@swc/jest": "^0.2.37",
56
56
  "@tsconfig/node22": "^22.0.0",
57
57
  "@types/jest": "^29.5.14",
58
58
  "@types/jsonwebtoken": "^9.0.9",
59
- "@types/node": "^22.13.5",
59
+ "@types/node": "^22.13.9",
60
60
  "@types/passport-http-bearer": "^1.0.41",
61
61
  "@types/supertest": "^6.0.2",
62
62
  "@types/uuid": "^10.0.0",
63
63
  "dotenv": "^16.4.7",
64
64
  "eslint": "^9.21.0",
65
- "eslint-config-prettier": "^10.0.1",
65
+ "eslint-config-prettier": "^10.0.2",
66
66
  "eslint-plugin-prettier": "^5.2.3",
67
67
  "jest": "^29.7.0",
68
68
  "jest-extended": "^4.0.2",
@@ -70,8 +70,8 @@
70
70
  "supertest": "^7.0.0",
71
71
  "ts-jest": "^29.2.6",
72
72
  "ts-node": "^10.9.2",
73
- "typescript": "^5.7.3",
74
- "typescript-eslint": "^8.25.0",
73
+ "typescript": "^5.8.2",
74
+ "typescript-eslint": "^8.26.0",
75
75
  "uuid": "^11.1.0"
76
76
  }
77
77
  }