@causa/runtime-google 0.33.1 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -2
- package/dist/app-check/guard.js +4 -2
- package/dist/identity-platform/identity-platform.strategy.js +4 -2
- package/dist/pubsub/publisher.d.ts +7 -13
- package/dist/pubsub/publisher.js +27 -17
- package/dist/pubsub/publisher.module.js +1 -2
- package/dist/spanner/entity-manager.d.ts +22 -18
- package/dist/spanner/entity-manager.js +6 -6
- package/dist/spanner/index.d.ts +1 -1
- package/dist/transaction/firestore-pubsub/runner.js +4 -2
- package/dist/transaction/index.d.ts +3 -0
- package/dist/transaction/index.js +3 -0
- package/dist/transaction/spanner-outbox/event.d.ts +27 -0
- package/dist/transaction/spanner-outbox/event.js +63 -0
- package/dist/transaction/spanner-outbox/index.d.ts +5 -0
- package/dist/transaction/spanner-outbox/index.js +4 -0
- package/dist/transaction/spanner-outbox/module.d.ts +28 -0
- package/dist/transaction/spanner-outbox/module.js +91 -0
- package/dist/transaction/spanner-outbox/runner.d.ts +19 -0
- package/dist/transaction/spanner-outbox/runner.js +31 -0
- package/dist/transaction/spanner-outbox/sender.d.ts +95 -0
- package/dist/transaction/spanner-outbox/sender.js +150 -0
- package/dist/transaction/spanner-pubsub/index.d.ts +0 -2
- package/dist/transaction/spanner-pubsub/index.js +0 -2
- package/dist/transaction/spanner-pubsub/runner.d.ts +3 -3
- package/dist/transaction/spanner-pubsub/runner.js +12 -27
- package/dist/transaction/{spanner-pubsub/state-transaction.d.ts → spanner-state-transaction.d.ts} +4 -5
- package/dist/transaction/{spanner-pubsub/state-transaction.js → spanner-state-transaction.js} +2 -3
- package/dist/transaction/spanner-transaction.d.ts +16 -0
- package/dist/transaction/spanner-transaction.js +20 -0
- package/dist/transaction/spanner-utils.d.ts +9 -0
- package/dist/transaction/spanner-utils.js +31 -0
- package/package.json +11 -11
- package/dist/transaction/spanner-pubsub/transaction.d.ts +0 -17
- package/dist/transaction/spanner-pubsub/transaction.js +0 -21
package/README.md
CHANGED
|
@@ -102,12 +102,24 @@ For testing, the `createDatabase` utility creates a temporary database, copying
|
|
|
102
102
|
|
|
103
103
|
### GCP-based Causa transaction runners
|
|
104
104
|
|
|
105
|
-
This package provides
|
|
105
|
+
This package provides the following `TransactionRunner`s:
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
- `SpannerPubSubTransactionRunner`
|
|
108
|
+
- `FirestorePubSubTransactionRunner`
|
|
109
|
+
- `SpannerOutboxTransactionRunner`
|
|
110
|
+
|
|
111
|
+
The first two use Pub/Sub and a `BufferEventTransaction` to publish events. They only differ by the service used to store the state.
|
|
112
|
+
|
|
113
|
+
The `SpannerPubSubTransactionRunner` uses a Spanner transaction as the underlying transaction for the `SpannerTransaction`, while the `FirestorePubSubTransactionRunner` uses a Firestore transaction for the `FirestorePubSubTransaction`. Both state transactions implement the `FindReplaceStateTransaction` interface, and therefore the runners can be used with the `VersionedEntityManager`.
|
|
108
114
|
|
|
109
115
|
One feature sets the `FirestorePubSubTransactionRunner` and its `FirestoreStateTransaction` apart: the handling of deleted entities using a separate, "soft-deleted document collection". Entities with a non-null `deletedAt` property are moved to a collection suffixed with `$deleted`, and an `_expirationDate` field is added to them. A TTL is expected to be set on this field. The `@SoftDeletedFirestoreCollection` decorator must be added to document classes that are meant to be handled using the `FirestorePubSubTransactionRunner`.
|
|
110
116
|
|
|
117
|
+
> [!CAUTION]
|
|
118
|
+
>
|
|
119
|
+
> `SpannerPubSubTransactionRunner` and `FirestorePubSubTransactionRunner` do not provide atomic guarantees between the state and the events being committed. This could result in events being lost, as they are published once the state transaction successfully committed. Prefer the `SpannerOutboxTransactionRunner` when applicable.
|
|
120
|
+
|
|
121
|
+
`SpannerOutboxTransactionRunner` implements the outbox pattern (from the base runtime's `OutboxTransactionRunner`), and uses the default injected `EventPublisher` (which can be the `PubSubPublisher`, if the corresponding module is imported). It requires an outbox table to be created in each database using the runner. See the documentation of the `SpannerOutboxEvent` for more information.
|
|
122
|
+
|
|
111
123
|
### Validation
|
|
112
124
|
|
|
113
125
|
The `@IsValidFirestoreId` validation decorator checks that a property is a string which is not `.` or `..`, and does not contain forward slashes. This ensures the property's value can be used as a Firestore document ID.
|
package/dist/app-check/guard.js
CHANGED
|
@@ -7,6 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
|
+
var AppCheckGuard_1;
|
|
10
11
|
import { Logger, UnauthenticatedError } from '@causa/runtime/nestjs';
|
|
11
12
|
import { Injectable, } from '@nestjs/common';
|
|
12
13
|
import { Reflector } from '@nestjs/core';
|
|
@@ -16,7 +17,7 @@ import { APP_CHECK_DISABLED_METADATA_KEY } from './app-check-disabled.decorator.
|
|
|
16
17
|
* A NestJS guard that verifies the App Check token in the request.
|
|
17
18
|
* The token is expected to be in the `X-Firebase-AppCheck` header.
|
|
18
19
|
*/
|
|
19
|
-
let AppCheckGuard = class AppCheckGuard {
|
|
20
|
+
let AppCheckGuard = AppCheckGuard_1 = class AppCheckGuard {
|
|
20
21
|
appCheck;
|
|
21
22
|
reflector;
|
|
22
23
|
logger;
|
|
@@ -24,6 +25,7 @@ let AppCheckGuard = class AppCheckGuard {
|
|
|
24
25
|
this.appCheck = appCheck;
|
|
25
26
|
this.reflector = reflector;
|
|
26
27
|
this.logger = logger;
|
|
28
|
+
this.logger.setContext(AppCheckGuard_1.name);
|
|
27
29
|
}
|
|
28
30
|
async canActivate(context) {
|
|
29
31
|
const isDisabled = this.reflector.getAllAndOverride(APP_CHECK_DISABLED_METADATA_KEY, [context.getHandler(), context.getClass()]);
|
|
@@ -45,7 +47,7 @@ let AppCheckGuard = class AppCheckGuard {
|
|
|
45
47
|
}
|
|
46
48
|
}
|
|
47
49
|
};
|
|
48
|
-
AppCheckGuard = __decorate([
|
|
50
|
+
AppCheckGuard = AppCheckGuard_1 = __decorate([
|
|
49
51
|
Injectable(),
|
|
50
52
|
__metadata("design:paramtypes", [AppCheck,
|
|
51
53
|
Reflector,
|
|
@@ -7,6 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
|
+
var IdentityPlatformStrategy_1;
|
|
10
11
|
import { Logger, UnauthenticatedError } from '@causa/runtime/nestjs';
|
|
11
12
|
import { Injectable } from '@nestjs/common';
|
|
12
13
|
import { ConfigService } from '@nestjs/config';
|
|
@@ -19,7 +20,7 @@ import { Strategy } from 'passport-http-bearer';
|
|
|
19
20
|
* The `IDENTITY_PLATFORM_STRATEGY_CHECK_REVOKED_TOKEN` configuration key can be set to `true` to also check whether the
|
|
20
21
|
* token was revoked. This implies a call to the Identity Platform, which will increase latency.
|
|
21
22
|
*/
|
|
22
|
-
let IdentityPlatformStrategy = class IdentityPlatformStrategy extends PassportStrategy(Strategy) {
|
|
23
|
+
let IdentityPlatformStrategy = IdentityPlatformStrategy_1 = class IdentityPlatformStrategy extends PassportStrategy(Strategy) {
|
|
23
24
|
auth;
|
|
24
25
|
configService;
|
|
25
26
|
logger;
|
|
@@ -32,6 +33,7 @@ let IdentityPlatformStrategy = class IdentityPlatformStrategy extends PassportSt
|
|
|
32
33
|
this.auth = auth;
|
|
33
34
|
this.configService = configService;
|
|
34
35
|
this.logger = logger;
|
|
36
|
+
this.logger.setContext(IdentityPlatformStrategy_1.name);
|
|
35
37
|
this.checkRevoked = this.configService.get('IDENTITY_PLATFORM_STRATEGY_CHECK_REVOKED_TOKEN', false);
|
|
36
38
|
}
|
|
37
39
|
async validate(token) {
|
|
@@ -56,7 +58,7 @@ let IdentityPlatformStrategy = class IdentityPlatformStrategy extends PassportSt
|
|
|
56
58
|
return user;
|
|
57
59
|
}
|
|
58
60
|
};
|
|
59
|
-
IdentityPlatformStrategy = __decorate([
|
|
61
|
+
IdentityPlatformStrategy = IdentityPlatformStrategy_1 = __decorate([
|
|
60
62
|
Injectable(),
|
|
61
63
|
__metadata("design:paramtypes", [Auth,
|
|
62
64
|
ConfigService,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type EventPublisher, type ObjectSerializer, type PublishOptions } from '@causa/runtime';
|
|
1
|
+
import { type EventPublisher, type ObjectSerializer, type PreparedEvent, type PublishOptions } from '@causa/runtime';
|
|
2
|
+
import { Logger } from '@causa/runtime/nestjs';
|
|
2
3
|
import { PubSub, type PublishOptions as TopicPublishOptions } from '@google-cloud/pubsub';
|
|
3
4
|
import type { OnApplicationShutdown } from '@nestjs/common';
|
|
4
|
-
import type { Logger } from 'pino';
|
|
5
5
|
/**
|
|
6
6
|
* Options for the {@link PubSubPublisher}.
|
|
7
7
|
*/
|
|
@@ -32,16 +32,12 @@ export type PubSubPublisherOptions = {
|
|
|
32
32
|
* This inherits and overrides the {@link PubSubPublisherOptions.publishOptions} for a given topic.
|
|
33
33
|
*/
|
|
34
34
|
topicPublishOptions?: Record<string, TopicPublishOptions>;
|
|
35
|
-
/**
|
|
36
|
-
* The logger to use.
|
|
37
|
-
* Defaults to {@link getDefaultLogger}.
|
|
38
|
-
*/
|
|
39
|
-
logger?: Logger;
|
|
40
35
|
};
|
|
41
36
|
/**
|
|
42
37
|
* An implementation of the {@link EventPublisher} using Google Pub/Sub as the broker.
|
|
43
38
|
*/
|
|
44
39
|
export declare class PubSubPublisher implements EventPublisher, OnApplicationShutdown {
|
|
40
|
+
private readonly logger;
|
|
45
41
|
/**
|
|
46
42
|
* The {@link PubSub} client to use.
|
|
47
43
|
*/
|
|
@@ -59,10 +55,6 @@ export declare class PubSubPublisher implements EventPublisher, OnApplicationShu
|
|
|
59
55
|
* A cache of Pub/Sub {@link Topic}s to which messages can be published.
|
|
60
56
|
*/
|
|
61
57
|
private readonly topicCache;
|
|
62
|
-
/**
|
|
63
|
-
* The logger to use.
|
|
64
|
-
*/
|
|
65
|
-
readonly logger: Logger;
|
|
66
58
|
/**
|
|
67
59
|
* The options to use when publishing messages.
|
|
68
60
|
* This is used to instantiate the Pub/Sub {@link Topic}s.
|
|
@@ -77,9 +69,10 @@ export declare class PubSubPublisher implements EventPublisher, OnApplicationShu
|
|
|
77
69
|
/**
|
|
78
70
|
* Creates a new {@link PubSubPublisher}.
|
|
79
71
|
*
|
|
72
|
+
* @param logger The logger to use.
|
|
80
73
|
* @param options Options for the publisher.
|
|
81
74
|
*/
|
|
82
|
-
constructor(options?: PubSubPublisherOptions);
|
|
75
|
+
constructor(logger: Logger, options?: PubSubPublisherOptions);
|
|
83
76
|
/**
|
|
84
77
|
* Returns the Pub/Sub {@link Topic} to which messages can be published for a given event topic.
|
|
85
78
|
* If the topic has not been used before, it will be created using the {@link PubSubPublisher.publishOptions}.
|
|
@@ -88,7 +81,8 @@ export declare class PubSubPublisher implements EventPublisher, OnApplicationShu
|
|
|
88
81
|
* @returns The Pub/Sub {@link Topic} to which messages can be published.
|
|
89
82
|
*/
|
|
90
83
|
private getTopic;
|
|
91
|
-
|
|
84
|
+
prepare(topic: string, event: object, options?: PublishOptions): Promise<PreparedEvent>;
|
|
85
|
+
publish(topicOrPreparedEvent: string | PreparedEvent, event?: object, options?: PublishOptions): Promise<void>;
|
|
92
86
|
flush(): Promise<void>;
|
|
93
87
|
onApplicationShutdown(): Promise<void>;
|
|
94
88
|
}
|
package/dist/pubsub/publisher.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { JsonObjectSerializer,
|
|
1
|
+
import { JsonObjectSerializer, } from '@causa/runtime';
|
|
2
|
+
import { Logger } from '@causa/runtime/nestjs';
|
|
2
3
|
import { PubSub, Topic, } from '@google-cloud/pubsub';
|
|
3
4
|
import { getConfigurationKeyForTopic } from './configuration.js';
|
|
4
5
|
import { PubSubTopicNotConfiguredError } from './errors.js';
|
|
@@ -14,6 +15,7 @@ const DEFAULT_PUBLISH_OPTIONS = {
|
|
|
14
15
|
* An implementation of the {@link EventPublisher} using Google Pub/Sub as the broker.
|
|
15
16
|
*/
|
|
16
17
|
export class PubSubPublisher {
|
|
18
|
+
logger;
|
|
17
19
|
/**
|
|
18
20
|
* The {@link PubSub} client to use.
|
|
19
21
|
*/
|
|
@@ -31,10 +33,6 @@ export class PubSubPublisher {
|
|
|
31
33
|
* A cache of Pub/Sub {@link Topic}s to which messages can be published.
|
|
32
34
|
*/
|
|
33
35
|
topicCache = {};
|
|
34
|
-
/**
|
|
35
|
-
* The logger to use.
|
|
36
|
-
*/
|
|
37
|
-
logger;
|
|
38
36
|
/**
|
|
39
37
|
* The options to use when publishing messages.
|
|
40
38
|
* This is used to instantiate the Pub/Sub {@link Topic}s.
|
|
@@ -49,16 +47,18 @@ export class PubSubPublisher {
|
|
|
49
47
|
/**
|
|
50
48
|
* Creates a new {@link PubSubPublisher}.
|
|
51
49
|
*
|
|
50
|
+
* @param logger The logger to use.
|
|
52
51
|
* @param options Options for the publisher.
|
|
53
52
|
*/
|
|
54
|
-
constructor(options = {}) {
|
|
53
|
+
constructor(logger, options = {}) {
|
|
54
|
+
this.logger = logger;
|
|
55
|
+
this.logger.setContext(PubSubPublisher.name);
|
|
55
56
|
this.pubSub = options.pubSub ?? new PubSub();
|
|
56
57
|
this.serializer = options.serializer ?? new JsonObjectSerializer();
|
|
57
58
|
this.getConfiguration =
|
|
58
59
|
options.configurationGetter ?? ((key) => process.env[key]);
|
|
59
60
|
this.publishOptions = options.publishOptions ?? DEFAULT_PUBLISH_OPTIONS;
|
|
60
61
|
this.topicPublishOptions = options.topicPublishOptions ?? {};
|
|
61
|
-
this.logger = options.logger ?? getDefaultLogger();
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
64
|
* Returns the Pub/Sub {@link Topic} to which messages can be published for a given event topic.
|
|
@@ -85,17 +85,11 @@ export class PubSubPublisher {
|
|
|
85
85
|
this.topicCache[topicName] = topic;
|
|
86
86
|
return topic;
|
|
87
87
|
}
|
|
88
|
-
async
|
|
88
|
+
async prepare(topic, event, options = {}) {
|
|
89
89
|
const data = await this.serializer.serialize(event);
|
|
90
|
-
const pubSubTopic = this.getTopic(topic);
|
|
91
90
|
const defaultAttributes = {};
|
|
92
|
-
const baseLogData = {
|
|
93
|
-
topic,
|
|
94
|
-
pubSubTopic: pubSubTopic.name,
|
|
95
|
-
};
|
|
96
91
|
if ('id' in event && typeof event.id === 'string') {
|
|
97
92
|
defaultAttributes.eventId = event.id;
|
|
98
|
-
baseLogData.eventId = event.id;
|
|
99
93
|
}
|
|
100
94
|
if ('producedAt' in event && event.producedAt instanceof Date) {
|
|
101
95
|
defaultAttributes.producedAt = event.producedAt.toISOString();
|
|
@@ -105,14 +99,29 @@ export class PubSubPublisher {
|
|
|
105
99
|
}
|
|
106
100
|
const attributes = {
|
|
107
101
|
...defaultAttributes,
|
|
108
|
-
...options
|
|
102
|
+
...options?.attributes,
|
|
103
|
+
};
|
|
104
|
+
const key = options?.key;
|
|
105
|
+
return { topic, data, attributes, key };
|
|
106
|
+
}
|
|
107
|
+
async publish(topicOrPreparedEvent, event, options = {}) {
|
|
108
|
+
const isPrepared = typeof topicOrPreparedEvent !== 'string';
|
|
109
|
+
const { topic, data, attributes, key } = isPrepared
|
|
110
|
+
? topicOrPreparedEvent
|
|
111
|
+
: await this.prepare(topicOrPreparedEvent, event, options);
|
|
112
|
+
const pubSubTopic = this.getTopic(topic);
|
|
113
|
+
const baseLogData = {
|
|
114
|
+
topic,
|
|
115
|
+
pubSubTopic: pubSubTopic.name,
|
|
109
116
|
};
|
|
110
|
-
|
|
117
|
+
if (attributes && 'eventId' in attributes) {
|
|
118
|
+
baseLogData.eventId = attributes.eventId;
|
|
119
|
+
}
|
|
111
120
|
try {
|
|
112
121
|
const pubSubMessageId = await pubSubTopic.publishMessage({
|
|
113
122
|
data,
|
|
114
123
|
attributes,
|
|
115
|
-
orderingKey,
|
|
124
|
+
orderingKey: key,
|
|
116
125
|
});
|
|
117
126
|
this.logger.info({ ...baseLogData, pubSubMessageId }, 'Published message to Pub/Sub.');
|
|
118
127
|
}
|
|
@@ -121,6 +130,7 @@ export class PubSubPublisher {
|
|
|
121
130
|
...baseLogData,
|
|
122
131
|
pubSubMessage: data.toString('base64'),
|
|
123
132
|
pubSubAttributes: attributes,
|
|
133
|
+
pubSubOrderingKey: key,
|
|
124
134
|
errorMessage: error.message,
|
|
125
135
|
errorStack: error.stack,
|
|
126
136
|
}, 'Failed to publish message to Pub/Sub.');
|
|
@@ -28,11 +28,10 @@ export class PubSubPublisherModule {
|
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
provide: PubSubPublisher,
|
|
31
|
-
useFactory: (pubSub, configurationGetter,
|
|
31
|
+
useFactory: (pubSub, configurationGetter, logger) => new PubSubPublisher(logger, {
|
|
32
32
|
...options,
|
|
33
33
|
pubSub,
|
|
34
34
|
configurationGetter,
|
|
35
|
-
logger,
|
|
36
35
|
}),
|
|
37
36
|
inject: [
|
|
38
37
|
PubSub,
|
|
@@ -8,6 +8,10 @@ import type { RecursivePartialEntity } from './types.js';
|
|
|
8
8
|
* Any Spanner transaction that can be used for reading.
|
|
9
9
|
*/
|
|
10
10
|
export type SpannerReadOnlyTransaction = Snapshot | Transaction;
|
|
11
|
+
/**
|
|
12
|
+
* A Spanner transaction that can be used for reading and writing.
|
|
13
|
+
*/
|
|
14
|
+
export type SpannerReadWriteTransaction = Transaction;
|
|
11
15
|
/**
|
|
12
16
|
* A key for a Spanner row.
|
|
13
17
|
*/
|
|
@@ -17,16 +21,16 @@ export type SpannerKey = (string | null)[];
|
|
|
17
21
|
*/
|
|
18
22
|
type WriteOperationOptions = {
|
|
19
23
|
/**
|
|
20
|
-
* The {@link
|
|
24
|
+
* The {@link SpannerReadWriteTransaction} to use.
|
|
21
25
|
*/
|
|
22
|
-
transaction?:
|
|
26
|
+
transaction?: SpannerReadWriteTransaction;
|
|
23
27
|
};
|
|
24
28
|
/**
|
|
25
29
|
* Base options for all read operations.
|
|
26
30
|
*/
|
|
27
31
|
type ReadOperationOptions = {
|
|
28
32
|
/**
|
|
29
|
-
* The {@link
|
|
33
|
+
* The {@link SpannerReadOnlyTransaction} to use.
|
|
30
34
|
*/
|
|
31
35
|
transaction?: SpannerReadOnlyTransaction;
|
|
32
36
|
};
|
|
@@ -42,7 +46,7 @@ type SnapshotOptions = {
|
|
|
42
46
|
/**
|
|
43
47
|
* A function that can be passed to the {@link SpannerEntityManager.snapshot} method.
|
|
44
48
|
*/
|
|
45
|
-
export type SnapshotFunction<T> = (snapshot:
|
|
49
|
+
export type SnapshotFunction<T> = (snapshot: SpannerReadOnlyTransaction) => Promise<T>;
|
|
46
50
|
/**
|
|
47
51
|
* A SQL statement run using {@link SpannerEntityManager.query}.
|
|
48
52
|
*/
|
|
@@ -196,16 +200,16 @@ export declare class SpannerEntityManager {
|
|
|
196
200
|
*/
|
|
197
201
|
findOneByKeyOrFail<T>(entityType: Type<T>, key: SpannerKey | SpannerKey[number], options?: FindOptions): Promise<T>;
|
|
198
202
|
/**
|
|
199
|
-
* Runs the provided function in a (read write) {@link
|
|
203
|
+
* Runs the provided function in a (read write) {@link SpannerReadWriteTransaction}.
|
|
200
204
|
* The function itself should not commit or rollback the transaction.
|
|
201
205
|
* If the function throws an error, the transaction will be rolled back.
|
|
202
206
|
*
|
|
203
207
|
* @param runFn The function to run in the transaction.
|
|
204
208
|
* @returns The return value of the function.
|
|
205
209
|
*/
|
|
206
|
-
transaction<T>(runFn: (transaction:
|
|
210
|
+
transaction<T>(runFn: (transaction: SpannerReadWriteTransaction) => Promise<T>): Promise<T>;
|
|
207
211
|
/**
|
|
208
|
-
* Runs the provided function in a
|
|
212
|
+
* Runs the provided function in a {@link SpannerReadOnlyTransaction}.
|
|
209
213
|
* The snapshot will be automatically released when the function returns.
|
|
210
214
|
*
|
|
211
215
|
* @param runFn The function to run in the transaction.
|
|
@@ -213,7 +217,7 @@ export declare class SpannerEntityManager {
|
|
|
213
217
|
*/
|
|
214
218
|
snapshot<T>(runFn: SnapshotFunction<T>): Promise<T>;
|
|
215
219
|
/**
|
|
216
|
-
* Runs the provided function in a
|
|
220
|
+
* Runs the provided function in a {@link SpannerReadOnlyTransaction}.
|
|
217
221
|
* The snapshot will be automatically released when the function returns.
|
|
218
222
|
*
|
|
219
223
|
* @param options The options to use when creating the snapshot.
|
|
@@ -230,8 +234,8 @@ export declare class SpannerEntityManager {
|
|
|
230
234
|
clear(entityType: Type, options?: WriteOperationOptions): Promise<void>;
|
|
231
235
|
/**
|
|
232
236
|
* Runs the given SQL statement in the database.
|
|
233
|
-
* By default, the statement is run in a
|
|
234
|
-
*
|
|
237
|
+
* By default, the statement is run in a {@link SpannerReadOnlyTransaction}. To perform a write operation, pass a
|
|
238
|
+
* {@link SpannerReadWriteTransaction} in the options.
|
|
235
239
|
*
|
|
236
240
|
* @param options Options for the operation.
|
|
237
241
|
* @param statement The SQL statement to run.
|
|
@@ -241,7 +245,7 @@ export declare class SpannerEntityManager {
|
|
|
241
245
|
query<T>(options: QueryOptions<T>, statement: SqlStatement): Promise<T[]>;
|
|
242
246
|
/**
|
|
243
247
|
* Runs the given SQL statement in the database.
|
|
244
|
-
* The statement is run in a
|
|
248
|
+
* The statement is run in a {@link SpannerReadOnlyTransaction}.
|
|
245
249
|
*
|
|
246
250
|
* @param statement The SQL statement to run.
|
|
247
251
|
* @returns The rows returned by the query.
|
|
@@ -331,22 +335,22 @@ export declare class SpannerEntityManager {
|
|
|
331
335
|
validateFn?: (entity: T) => void;
|
|
332
336
|
}): Promise<T>;
|
|
333
337
|
/**
|
|
334
|
-
* Runs the given "read-write" function on a transaction. If a transaction is not passed, a new
|
|
335
|
-
* created instead.
|
|
338
|
+
* Runs the given "read-write" function on a transaction. If a transaction is not passed, a new
|
|
339
|
+
* {@link SpannerReadWriteTransaction} is created instead.
|
|
336
340
|
*
|
|
337
341
|
* @param transaction The transaction to use. If `undefined`, a new transaction is created.
|
|
338
342
|
* @param fn The function to run on the transaction.
|
|
339
343
|
* @returns The result of the function.
|
|
340
344
|
*/
|
|
341
|
-
runInExistingOrNewTransaction<T>(transaction:
|
|
345
|
+
runInExistingOrNewTransaction<T>(transaction: SpannerReadWriteTransaction | undefined, fn: (transaction: SpannerReadWriteTransaction) => Promise<T>): Promise<T>;
|
|
342
346
|
/**
|
|
343
|
-
* Runs the given "read-only" function on a transaction. If a transaction is not passed, a new
|
|
344
|
-
* created instead.
|
|
347
|
+
* Runs the given "read-only" function on a transaction. If a transaction is not passed, a new
|
|
348
|
+
* {@link SpannerReadOnlyTransaction} is created instead.
|
|
345
349
|
*
|
|
346
|
-
* @param transaction The transaction to use. If `undefined`, a new {@link
|
|
350
|
+
* @param transaction The transaction to use. If `undefined`, a new {@link SpannerReadOnlyTransaction} is created.
|
|
347
351
|
* @param fn The function to run on the transaction.
|
|
348
352
|
* @returns The result of the function.
|
|
349
353
|
*/
|
|
350
|
-
runInExistingOrNewReadOnlyTransaction<T>(transaction: SpannerReadOnlyTransaction | undefined, fn:
|
|
354
|
+
runInExistingOrNewReadOnlyTransaction<T>(transaction: SpannerReadOnlyTransaction | undefined, fn: SnapshotFunction<T>): Promise<T>;
|
|
351
355
|
}
|
|
352
356
|
export {};
|
|
@@ -202,7 +202,7 @@ let SpannerEntityManager = class SpannerEntityManager {
|
|
|
202
202
|
return entity;
|
|
203
203
|
}
|
|
204
204
|
/**
|
|
205
|
-
* Runs the provided function in a (read write) {@link
|
|
205
|
+
* Runs the provided function in a (read write) {@link SpannerReadWriteTransaction}.
|
|
206
206
|
* The function itself should not commit or rollback the transaction.
|
|
207
207
|
* If the function throws an error, the transaction will be rolled back.
|
|
208
208
|
*
|
|
@@ -440,8 +440,8 @@ let SpannerEntityManager = class SpannerEntityManager {
|
|
|
440
440
|
});
|
|
441
441
|
}
|
|
442
442
|
/**
|
|
443
|
-
* Runs the given "read-write" function on a transaction. If a transaction is not passed, a new
|
|
444
|
-
* created instead.
|
|
443
|
+
* Runs the given "read-write" function on a transaction. If a transaction is not passed, a new
|
|
444
|
+
* {@link SpannerReadWriteTransaction} is created instead.
|
|
445
445
|
*
|
|
446
446
|
* @param transaction The transaction to use. If `undefined`, a new transaction is created.
|
|
447
447
|
* @param fn The function to run on the transaction.
|
|
@@ -459,10 +459,10 @@ let SpannerEntityManager = class SpannerEntityManager {
|
|
|
459
459
|
return this.transaction(fn);
|
|
460
460
|
}
|
|
461
461
|
/**
|
|
462
|
-
* Runs the given "read-only" function on a transaction. If a transaction is not passed, a new
|
|
463
|
-
* created instead.
|
|
462
|
+
* Runs the given "read-only" function on a transaction. If a transaction is not passed, a new
|
|
463
|
+
* {@link SpannerReadOnlyTransaction} is created instead.
|
|
464
464
|
*
|
|
465
|
-
* @param transaction The transaction to use. If `undefined`, a new {@link
|
|
465
|
+
* @param transaction The transaction to use. If `undefined`, a new {@link SpannerReadOnlyTransaction} is created.
|
|
466
466
|
* @param fn The function to run on the transaction.
|
|
467
467
|
* @returns The result of the function.
|
|
468
468
|
*/
|
package/dist/spanner/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { SpannerColumn } from './column.decorator.js';
|
|
2
2
|
export { SPANNER_SESSION_POOL_OPTIONS_FOR_CLOUD_FUNCTIONS, SPANNER_SESSION_POOL_OPTIONS_FOR_SERVICE, catchSpannerDatabaseErrors, getDefaultSpannerDatabaseForCloudFunction, } from './database.js';
|
|
3
3
|
export { SpannerEntityManager } from './entity-manager.js';
|
|
4
|
-
export type { SpannerKey, SpannerReadOnlyTransaction, } from './entity-manager.js';
|
|
4
|
+
export type { SpannerKey, SpannerReadOnlyTransaction, SpannerReadWriteTransaction, } from './entity-manager.js';
|
|
5
5
|
export * from './errors.js';
|
|
6
6
|
export { SpannerHealthIndicator } from './healthcheck.js';
|
|
7
7
|
export { SpannerModule } from './module.js';
|
|
@@ -7,6 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
|
+
var FirestorePubSubTransactionRunner_1;
|
|
10
11
|
import { BufferEventTransaction, TransactionRunner } from '@causa/runtime';
|
|
11
12
|
import { Logger } from '@causa/runtime/nestjs';
|
|
12
13
|
import { Firestore } from '@google-cloud/firestore';
|
|
@@ -22,7 +23,7 @@ import { FirestorePubSubTransaction } from './transaction.js';
|
|
|
22
23
|
* This runner and the transaction use the {@link FirestoreStateTransaction}, which handles soft-deleted documents. All
|
|
23
24
|
* entities that are written to the state should be decorated with the `SoftDeletedFirestoreCollection` decorator.
|
|
24
25
|
*/
|
|
25
|
-
let FirestorePubSubTransactionRunner = class FirestorePubSubTransactionRunner extends TransactionRunner {
|
|
26
|
+
let FirestorePubSubTransactionRunner = FirestorePubSubTransactionRunner_1 = class FirestorePubSubTransactionRunner extends TransactionRunner {
|
|
26
27
|
firestore;
|
|
27
28
|
pubSubPublisher;
|
|
28
29
|
collectionResolver;
|
|
@@ -33,6 +34,7 @@ let FirestorePubSubTransactionRunner = class FirestorePubSubTransactionRunner ex
|
|
|
33
34
|
this.pubSubPublisher = pubSubPublisher;
|
|
34
35
|
this.collectionResolver = collectionResolver;
|
|
35
36
|
this.logger = logger;
|
|
37
|
+
this.logger.setContext(FirestorePubSubTransactionRunner_1.name);
|
|
36
38
|
}
|
|
37
39
|
async run(runFn) {
|
|
38
40
|
this.logger.info('Creating a Firestore Pub/Sub transaction.');
|
|
@@ -49,7 +51,7 @@ let FirestorePubSubTransactionRunner = class FirestorePubSubTransactionRunner ex
|
|
|
49
51
|
return [result];
|
|
50
52
|
}
|
|
51
53
|
};
|
|
52
|
-
FirestorePubSubTransactionRunner = __decorate([
|
|
54
|
+
FirestorePubSubTransactionRunner = FirestorePubSubTransactionRunner_1 = __decorate([
|
|
53
55
|
Injectable(),
|
|
54
56
|
__metadata("design:paramtypes", [Firestore,
|
|
55
57
|
PubSubPublisher, Object, Logger])
|
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
export * from './firestore-pubsub/index.js';
|
|
2
|
+
export * from './spanner-outbox/index.js';
|
|
2
3
|
export * from './spanner-pubsub/index.js';
|
|
4
|
+
export { SpannerStateTransaction } from './spanner-state-transaction.js';
|
|
5
|
+
export { SpannerTransaction } from './spanner-transaction.js';
|
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
export * from './firestore-pubsub/index.js';
|
|
2
|
+
export * from './spanner-outbox/index.js';
|
|
2
3
|
export * from './spanner-pubsub/index.js';
|
|
4
|
+
export { SpannerStateTransaction } from './spanner-state-transaction.js';
|
|
5
|
+
export { SpannerTransaction } from './spanner-transaction.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { EventAttributes, OutboxEvent } from '@causa/runtime';
|
|
2
|
+
/**
|
|
3
|
+
* A Spanner table that implements the {@link OutboxEvent} interface, such that it can be used to store outbox event.
|
|
4
|
+
*
|
|
5
|
+
* The full DDL for the table to be used by the outbox transaction runner is:
|
|
6
|
+
*
|
|
7
|
+
* ```sql
|
|
8
|
+
* CREATE TABLE OutboxEvent (
|
|
9
|
+
* id STRING(36) NOT NULL,
|
|
10
|
+
* topic STRING(MAX) NOT NULL,
|
|
11
|
+
* data BYTES(MAX) NOT NULL,
|
|
12
|
+
* attributes JSON NOT NULL,
|
|
13
|
+
* leaseExpiration TIMESTAMP,
|
|
14
|
+
* -- 20 is the number of shards.
|
|
15
|
+
* shard INT64 AS (MOD(ABS(FARM_FINGERPRINT(id)), 20)),
|
|
16
|
+
* ) PRIMARY KEY (id);
|
|
17
|
+
* CREATE INDEX OutboxEventsByShardAndLeaseExpiration ON OutboxEvent(shard, leaseExpiration)
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare class SpannerOutboxEvent implements OutboxEvent {
|
|
21
|
+
constructor(init: SpannerOutboxEvent);
|
|
22
|
+
readonly id: string;
|
|
23
|
+
readonly topic: string;
|
|
24
|
+
readonly data: Buffer;
|
|
25
|
+
readonly attributes: EventAttributes;
|
|
26
|
+
readonly leaseExpiration: Date | null;
|
|
27
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { SpannerColumn, SpannerTable } from '../../spanner/index.js';
|
|
11
|
+
/**
|
|
12
|
+
* A Spanner table that implements the {@link OutboxEvent} interface, such that it can be used to store outbox event.
|
|
13
|
+
*
|
|
14
|
+
* The full DDL for the table to be used by the outbox transaction runner is:
|
|
15
|
+
*
|
|
16
|
+
* ```sql
|
|
17
|
+
* CREATE TABLE OutboxEvent (
|
|
18
|
+
* id STRING(36) NOT NULL,
|
|
19
|
+
* topic STRING(MAX) NOT NULL,
|
|
20
|
+
* data BYTES(MAX) NOT NULL,
|
|
21
|
+
* attributes JSON NOT NULL,
|
|
22
|
+
* leaseExpiration TIMESTAMP,
|
|
23
|
+
* -- 20 is the number of shards.
|
|
24
|
+
* shard INT64 AS (MOD(ABS(FARM_FINGERPRINT(id)), 20)),
|
|
25
|
+
* ) PRIMARY KEY (id);
|
|
26
|
+
* CREATE INDEX OutboxEventsByShardAndLeaseExpiration ON OutboxEvent(shard, leaseExpiration)
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
let SpannerOutboxEvent = class SpannerOutboxEvent {
|
|
30
|
+
constructor(init) {
|
|
31
|
+
Object.assign(this, init);
|
|
32
|
+
}
|
|
33
|
+
id;
|
|
34
|
+
topic;
|
|
35
|
+
data;
|
|
36
|
+
attributes;
|
|
37
|
+
leaseExpiration;
|
|
38
|
+
};
|
|
39
|
+
__decorate([
|
|
40
|
+
SpannerColumn(),
|
|
41
|
+
__metadata("design:type", String)
|
|
42
|
+
], SpannerOutboxEvent.prototype, "id", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
SpannerColumn(),
|
|
45
|
+
__metadata("design:type", String)
|
|
46
|
+
], SpannerOutboxEvent.prototype, "topic", void 0);
|
|
47
|
+
__decorate([
|
|
48
|
+
SpannerColumn(),
|
|
49
|
+
__metadata("design:type", Buffer)
|
|
50
|
+
], SpannerOutboxEvent.prototype, "data", void 0);
|
|
51
|
+
__decorate([
|
|
52
|
+
SpannerColumn({ isJson: true }),
|
|
53
|
+
__metadata("design:type", Object)
|
|
54
|
+
], SpannerOutboxEvent.prototype, "attributes", void 0);
|
|
55
|
+
__decorate([
|
|
56
|
+
SpannerColumn(),
|
|
57
|
+
__metadata("design:type", Object)
|
|
58
|
+
], SpannerOutboxEvent.prototype, "leaseExpiration", void 0);
|
|
59
|
+
SpannerOutboxEvent = __decorate([
|
|
60
|
+
SpannerTable({ name: 'OutboxEvent', primaryKey: ['id'] }),
|
|
61
|
+
__metadata("design:paramtypes", [SpannerOutboxEvent])
|
|
62
|
+
], SpannerOutboxEvent);
|
|
63
|
+
export { SpannerOutboxEvent };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { SpannerOutboxEvent } from './event.js';
|
|
2
|
+
export { SpannerOutboxTransactionModule } from './module.js';
|
|
3
|
+
export { SpannerOutboxTransactionRunner } from './runner.js';
|
|
4
|
+
export type { SpannerOutboxTransaction } from './runner.js';
|
|
5
|
+
export { SpannerOutboxSender } from './sender.js';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { OutboxEvent } from '@causa/runtime';
|
|
2
|
+
import type { DynamicModule, Type } from '@nestjs/common';
|
|
3
|
+
import { type SpannerOutboxSenderOptions } from './sender.js';
|
|
4
|
+
/**
|
|
5
|
+
* Options for the {@link SpannerOutboxTransactionModule}.
|
|
6
|
+
*/
|
|
7
|
+
export type SpannerOutboxTransactionModuleOptions = SpannerOutboxSenderOptions & {
|
|
8
|
+
/**
|
|
9
|
+
* The type of {@link OutboxEvent} used by the {@link SpannerOutboxTransactionRunner}.
|
|
10
|
+
* This should be a valid class decorated with `@SpannerTable`.
|
|
11
|
+
* Defaults to {@link SpannerOutboxEvent}.
|
|
12
|
+
*/
|
|
13
|
+
outboxEventType?: Type<OutboxEvent>;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* The module providing the {@link SpannerOutboxTransactionRunner}.
|
|
17
|
+
* This assumes the `SpannerModule` and an {@link EventPublisher} are available (as well as the `LoggerModule`).
|
|
18
|
+
*/
|
|
19
|
+
export declare class SpannerOutboxTransactionModule {
|
|
20
|
+
/**
|
|
21
|
+
* Initializes the {@link SpannerOutboxTransactionModule} with the given options.
|
|
22
|
+
* The returned module is always global.
|
|
23
|
+
*
|
|
24
|
+
* @param options Options for the {@link SpannerOutboxTransactionModule}.
|
|
25
|
+
* @returns The module.
|
|
26
|
+
*/
|
|
27
|
+
static forRoot(options?: SpannerOutboxTransactionModuleOptions): DynamicModule;
|
|
28
|
+
}
|