@effect-app/infra 4.0.0-beta.13 → 4.0.0-beta.131
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/CHANGELOG.md +864 -0
- package/dist/CUPS.d.ts +13 -5
- package/dist/CUPS.d.ts.map +1 -1
- package/dist/CUPS.js +10 -12
- package/dist/Emailer/service.d.ts +2 -2
- package/dist/Emailer/service.d.ts.map +1 -1
- package/dist/Emailer/service.js +3 -3
- package/dist/MainFiberSet.d.ts +2 -2
- package/dist/MainFiberSet.d.ts.map +1 -1
- package/dist/MainFiberSet.js +3 -3
- package/dist/Model/Repository/Registry.d.ts +20 -0
- package/dist/Model/Repository/Registry.d.ts.map +1 -0
- package/dist/Model/Repository/Registry.js +17 -0
- package/dist/Model/Repository/ext.d.ts +21 -3
- package/dist/Model/Repository/ext.d.ts.map +1 -1
- package/dist/Model/Repository/ext.js +54 -2
- package/dist/Model/Repository/internal/internal.d.ts +4 -4
- package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
- package/dist/Model/Repository/internal/internal.js +31 -21
- package/dist/Model/Repository/makeRepo.d.ts +6 -5
- package/dist/Model/Repository/makeRepo.d.ts.map +1 -1
- package/dist/Model/Repository/makeRepo.js +4 -1
- package/dist/Model/Repository/service.d.ts +27 -22
- package/dist/Model/Repository/service.d.ts.map +1 -1
- package/dist/Model/Repository/validation.d.ts +59 -9
- package/dist/Model/Repository/validation.d.ts.map +1 -1
- package/dist/Model/Repository.d.ts +1 -0
- package/dist/Model/Repository.d.ts.map +1 -1
- package/dist/Model/Repository.js +2 -1
- package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -1
- package/dist/Model/query/new-kid-interpreter.js +3 -3
- package/dist/Model.d.ts +1 -0
- package/dist/Model.d.ts.map +1 -1
- package/dist/Model.js +2 -1
- package/dist/Operations.d.ts +4 -4
- package/dist/Operations.d.ts.map +1 -1
- package/dist/Operations.js +56 -59
- package/dist/OperationsRepo.d.ts +4 -4
- package/dist/OperationsRepo.d.ts.map +1 -1
- package/dist/OperationsRepo.js +3 -3
- package/dist/QueueMaker/SQLQueue.d.ts +3 -6
- package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
- package/dist/QueueMaker/SQLQueue.js +105 -114
- package/dist/QueueMaker/errors.d.ts +1 -1
- package/dist/QueueMaker/errors.d.ts.map +1 -1
- package/dist/QueueMaker/memQueue.d.ts +6 -3
- package/dist/QueueMaker/memQueue.d.ts.map +1 -1
- package/dist/QueueMaker/memQueue.js +51 -62
- package/dist/QueueMaker/sbqueue.d.ts +5 -2
- package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
- package/dist/QueueMaker/sbqueue.js +36 -52
- package/dist/RequestContext.d.ts +51 -21
- package/dist/RequestContext.d.ts.map +1 -1
- package/dist/RequestContext.js +5 -5
- package/dist/RequestFiberSet.d.ts +2 -2
- package/dist/RequestFiberSet.d.ts.map +1 -1
- package/dist/RequestFiberSet.js +5 -5
- package/dist/Store/ContextMapContainer.d.ts +18 -2
- package/dist/Store/ContextMapContainer.d.ts.map +1 -1
- package/dist/Store/ContextMapContainer.js +13 -3
- package/dist/Store/Cosmos.d.ts.map +1 -1
- package/dist/Store/Cosmos.js +308 -242
- package/dist/Store/Disk.d.ts +1 -1
- package/dist/Store/Disk.d.ts.map +1 -1
- package/dist/Store/Disk.js +25 -22
- package/dist/Store/Memory.d.ts +3 -3
- package/dist/Store/Memory.d.ts.map +1 -1
- package/dist/Store/Memory.js +27 -22
- package/dist/Store/SQL/Pg.d.ts +4 -0
- package/dist/Store/SQL/Pg.d.ts.map +1 -0
- package/dist/Store/SQL/Pg.js +189 -0
- package/dist/Store/SQL/query.d.ts +38 -0
- package/dist/Store/SQL/query.d.ts.map +1 -0
- package/dist/Store/SQL/query.js +367 -0
- package/dist/Store/SQL.d.ts +20 -0
- package/dist/Store/SQL.d.ts.map +1 -0
- package/dist/Store/SQL.js +381 -0
- package/dist/Store/index.d.ts +4 -1
- package/dist/Store/index.d.ts.map +1 -1
- package/dist/Store/index.js +15 -3
- package/dist/Store/service.d.ts +16 -5
- package/dist/Store/service.d.ts.map +1 -1
- package/dist/Store/service.js +24 -6
- package/dist/Store/utils.d.ts.map +1 -1
- package/dist/Store/utils.js +3 -4
- package/dist/adapters/ServiceBus.d.ts +6 -6
- package/dist/adapters/ServiceBus.d.ts.map +1 -1
- package/dist/adapters/ServiceBus.js +13 -15
- package/dist/adapters/cosmos-client.d.ts +2 -2
- package/dist/adapters/cosmos-client.d.ts.map +1 -1
- package/dist/adapters/cosmos-client.js +3 -3
- package/dist/adapters/logger.d.ts.map +1 -1
- package/dist/adapters/memQueue.d.ts +2 -2
- package/dist/adapters/memQueue.d.ts.map +1 -1
- package/dist/adapters/memQueue.js +3 -3
- package/dist/adapters/mongo-client.d.ts +2 -2
- package/dist/adapters/mongo-client.d.ts.map +1 -1
- package/dist/adapters/mongo-client.js +3 -3
- package/dist/adapters/redis-client.d.ts +2 -2
- package/dist/adapters/redis-client.d.ts.map +1 -1
- package/dist/adapters/redis-client.js +3 -3
- package/dist/api/ContextProvider.d.ts +6 -6
- package/dist/api/ContextProvider.d.ts.map +1 -1
- package/dist/api/ContextProvider.js +6 -6
- package/dist/api/internal/auth.d.ts +42 -4
- package/dist/api/internal/auth.d.ts.map +1 -1
- package/dist/api/internal/auth.js +160 -29
- package/dist/api/internal/events.d.ts +2 -2
- package/dist/api/internal/events.d.ts.map +1 -1
- package/dist/api/internal/events.js +11 -7
- package/dist/api/layerUtils.d.ts +5 -5
- package/dist/api/layerUtils.d.ts.map +1 -1
- package/dist/api/layerUtils.js +5 -5
- package/dist/api/routing/middleware/RouterMiddleware.d.ts +3 -3
- package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.d.ts +37 -1
- package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.js +45 -14
- package/dist/api/routing.d.ts +4 -6
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +13 -6
- package/dist/api/setupRequest.d.ts +6 -3
- package/dist/api/setupRequest.d.ts.map +1 -1
- package/dist/api/setupRequest.js +11 -6
- package/dist/errorReporter.d.ts +3 -3
- package/dist/errorReporter.d.ts.map +1 -1
- package/dist/errorReporter.js +16 -23
- package/dist/logger.d.ts.map +1 -1
- package/dist/rateLimit.d.ts +8 -2
- package/dist/rateLimit.d.ts.map +1 -1
- package/dist/rateLimit.js +5 -11
- package/examples/query.ts +30 -26
- package/package.json +36 -22
- package/src/CUPS.ts +9 -11
- package/src/Emailer/service.ts +2 -2
- package/src/MainFiberSet.ts +2 -2
- package/src/Model/Repository/Registry.ts +33 -0
- package/src/Model/Repository/ext.ts +93 -6
- package/src/Model/Repository/internal/internal.ts +84 -76
- package/src/Model/Repository/makeRepo.ts +11 -8
- package/src/Model/Repository/service.ts +31 -22
- package/src/Model/Repository.ts +1 -0
- package/src/Model/query/new-kid-interpreter.ts +2 -2
- package/src/Model.ts +1 -0
- package/src/Operations.ts +78 -113
- package/src/OperationsRepo.ts +2 -2
- package/src/QueueMaker/SQLQueue.ts +121 -151
- package/src/QueueMaker/memQueue.ts +82 -103
- package/src/QueueMaker/sbqueue.ts +55 -85
- package/src/RequestContext.ts +4 -4
- package/src/RequestFiberSet.ts +4 -4
- package/src/Store/ContextMapContainer.ts +41 -2
- package/src/Store/Cosmos.ts +437 -343
- package/src/Store/Disk.ts +52 -49
- package/src/Store/Memory.ts +54 -48
- package/src/Store/SQL/Pg.ts +318 -0
- package/src/Store/SQL/query.ts +409 -0
- package/src/Store/SQL.ts +668 -0
- package/src/Store/index.ts +17 -2
- package/src/Store/service.ts +31 -7
- package/src/Store/utils.ts +23 -22
- package/src/adapters/ServiceBus.ts +111 -115
- package/src/adapters/cosmos-client.ts +2 -2
- package/src/adapters/memQueue.ts +2 -2
- package/src/adapters/mongo-client.ts +2 -2
- package/src/adapters/redis-client.ts +2 -2
- package/src/api/ContextProvider.ts +11 -11
- package/src/api/internal/auth.ts +246 -44
- package/src/api/internal/events.ts +14 -9
- package/src/api/layerUtils.ts +8 -8
- package/src/api/routing/middleware/RouterMiddleware.ts +4 -4
- package/src/api/routing/middleware/middleware.ts +52 -12
- package/src/api/routing.ts +17 -7
- package/src/api/setupRequest.ts +27 -7
- package/src/errorReporter.ts +58 -72
- package/src/rateLimit.ts +30 -22
- package/test/auth.test.ts +101 -0
- package/test/contextProvider.test.ts +11 -11
- package/test/controller.test.ts +18 -13
- package/test/dist/auth.test.d.ts.map +1 -0
- package/test/dist/contextProvider.test.d.ts.map +1 -1
- package/test/dist/controller.test.d.ts.map +1 -1
- package/test/dist/date-query.test.d.ts.map +1 -0
- package/test/dist/fixtures.d.ts +19 -9
- package/test/dist/fixtures.d.ts.map +1 -1
- package/test/dist/fixtures.js +11 -9
- package/test/dist/query.test.d.ts.map +1 -1
- package/test/dist/rawQuery.test.d.ts.map +1 -1
- package/test/dist/repository-ext.test.d.ts.map +1 -0
- package/test/dist/requires.test.d.ts.map +1 -1
- package/test/dist/routing-interruptibility.test.d.ts.map +1 -0
- package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
- package/test/dist/sql-store.test.d.ts.map +1 -0
- package/test/fixtures.ts +10 -8
- package/test/query.test.ts +209 -31
- package/test/rawQuery.test.ts +23 -19
- package/test/repository-ext.test.ts +58 -0
- package/test/requires.test.ts +6 -5
- package/test/routing-interruptibility.test.ts +63 -0
- package/test/rpc-multi-middleware.test.ts +72 -3
- package/test/sql-store.test.ts +1064 -0
- package/test/validateSample.test.ts +12 -9
- package/tsconfig.json +0 -1
package/src/Store/Cosmos.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { InfraLogger } from "../logger.js"
|
|
|
9
9
|
import type { FieldValues } from "../Model/filter/types.js"
|
|
10
10
|
import { type RawQuery } from "../Model/query.js"
|
|
11
11
|
import { buildWhereCosmosQuery3, logQuery } from "./Cosmos/query.js"
|
|
12
|
+
import { storeId } from "./Memory.js"
|
|
12
13
|
import { type FilterArgs, type PersistenceModelType, type StorageConfig, type Store, type StoreConfig, StoreMaker } from "./service.js"
|
|
13
14
|
|
|
14
15
|
const makeMapId =
|
|
@@ -25,148 +26,219 @@ class CosmosDbOperationError {
|
|
|
25
26
|
constructor(readonly message: string, readonly raw?: unknown) {}
|
|
26
27
|
} // TODO: Retry operation when running into RU limit.
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
29
|
+
const makeCosmosStore = Effect.fnUntraced(function*({ prefix }: StorageConfig) {
|
|
30
|
+
const { db } = yield* CosmosClient
|
|
31
|
+
return {
|
|
32
|
+
make: Effect.fnUntraced(function*<IdKey extends keyof Encoded, Encoded extends FieldValues, R = never, E = never>(
|
|
33
|
+
name: string,
|
|
34
|
+
idKey: IdKey,
|
|
35
|
+
seed?: Effect.Effect<Iterable<Encoded>, E, R>,
|
|
36
|
+
config?: StoreConfig<Encoded>
|
|
37
|
+
) {
|
|
38
|
+
const mapId = makeMapId<IdKey, Encoded>(idKey)
|
|
39
|
+
const mapReverseId = makeReverseMapId<IdKey, Encoded>(idKey)
|
|
40
|
+
type PM = PersistenceModelType<Encoded>
|
|
41
|
+
type PMCosmos = PersistenceModelType<Omit<Encoded, IdKey> & { id: string }>
|
|
42
|
+
const containerId = `${prefix}${name}`
|
|
43
|
+
yield* Effect.promise(() =>
|
|
44
|
+
db.containers.createIfNotExists(dropUndefinedT({
|
|
45
|
+
id: containerId,
|
|
46
|
+
uniqueKeyPolicy: config?.uniqueKeys
|
|
47
|
+
? { uniqueKeys: config.uniqueKeys }
|
|
48
|
+
: undefined,
|
|
49
|
+
partitionKey: {
|
|
50
|
+
paths: ["/_partitionKey"],
|
|
51
|
+
version: 2 // support large partitionkeys so that the hash is not based on just the first 100 bytes!
|
|
52
|
+
}
|
|
53
|
+
}))
|
|
54
|
+
)
|
|
52
55
|
|
|
53
|
-
|
|
56
|
+
const basePartitionKey = config?.partitionValue() ?? "primary"
|
|
57
|
+
const nsPrefix = (ns: string) => ns === "primary" ? "" : `${ns}::`
|
|
58
|
+
const nsPartitionValue = (ns: string, e?: Encoded) => {
|
|
59
|
+
const base = config?.partitionValue(e) ?? "primary"
|
|
60
|
+
return `${nsPrefix(ns)}${base}`
|
|
61
|
+
}
|
|
62
|
+
const nsBasePartitionKey = (ns: string) => `${nsPrefix(ns)}${basePartitionKey}`
|
|
63
|
+
const resolveNamespace = !config?.allowNamespace
|
|
64
|
+
? Effect.succeed("primary")
|
|
65
|
+
: storeId.asEffect().pipe(Effect.map((namespace) => {
|
|
66
|
+
if (namespace !== "primary" && !config.allowNamespace!(namespace)) {
|
|
67
|
+
throw new Error(`Namespace ${namespace} not allowed!`)
|
|
68
|
+
}
|
|
69
|
+
return namespace
|
|
70
|
+
}))
|
|
54
71
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
72
|
+
const defaultValues = config?.defaultValues ?? {}
|
|
73
|
+
const container = db.container(containerId)
|
|
74
|
+
const bulk = container.items.bulk.bind(container.items)
|
|
75
|
+
const execBatch = container.items.batch.bind(container.items)
|
|
76
|
+
// TODO: move the marker to a separate container and get rid of the checks on every query
|
|
77
|
+
// then need to clean up the actual data.. perhaps first do with a config toggle to prescribe to it.
|
|
78
|
+
const importedMarkerId = containerId
|
|
62
79
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// partitionKey: config?.partitionValue(x)
|
|
84
|
-
}),
|
|
85
|
-
onSome: (eTag) =>
|
|
86
|
-
dropUndefinedT({
|
|
87
|
-
operationType: "Replace" as const,
|
|
88
|
-
id: x[idKey],
|
|
89
|
-
resourceBody: {
|
|
90
|
-
...Struct.omit(x, ["_etag", idKey]),
|
|
91
|
-
id: x[idKey],
|
|
92
|
-
_partitionKey: config?.partitionValue(x)
|
|
93
|
-
},
|
|
94
|
-
ifMatch: eTag
|
|
95
|
-
// don't use this or we get an error that the request and some item partition key dont match - makese no sense
|
|
96
|
-
// partitionKey: config?.partitionValue(x)
|
|
97
|
-
})
|
|
98
|
-
})
|
|
99
|
-
] as const
|
|
80
|
+
const ctx = yield* Effect.context<R>()
|
|
81
|
+
const seedCache = new Map<string, Effect.Effect<void>>()
|
|
82
|
+
const makeSeedEffect = (ns: string) => {
|
|
83
|
+
const markerId = ns === "primary" ? importedMarkerId : `${importedMarkerId}::${ns}`
|
|
84
|
+
return Effect
|
|
85
|
+
.promise(() =>
|
|
86
|
+
container
|
|
87
|
+
.item(markerId, markerId)
|
|
88
|
+
.read<{ id: string }>()
|
|
89
|
+
.then(({ resource }) => Option.fromNullishOr(resource))
|
|
90
|
+
)
|
|
91
|
+
.pipe(
|
|
92
|
+
Effect.flatMap((marker) => {
|
|
93
|
+
if (Option.isSome(marker)) return Effect.void
|
|
94
|
+
return InfraLogger.logInfo(`Creating mock data for ${name} (namespace: ${ns})`).pipe(
|
|
95
|
+
Effect.andThen(seed!),
|
|
96
|
+
Effect.flatMap((m) =>
|
|
97
|
+
Effect.flatMapOption(
|
|
98
|
+
Effect.succeed(toNonEmptyArray([...m])),
|
|
99
|
+
(a) => bulkSetInternal(a, ns).pipe(Effect.orDie)
|
|
100
100
|
)
|
|
101
|
-
|
|
101
|
+
),
|
|
102
|
+
Effect.andThen(
|
|
103
|
+
Effect.promise(() =>
|
|
104
|
+
container.items.create({
|
|
105
|
+
_partitionKey: markerId,
|
|
106
|
+
id: markerId,
|
|
107
|
+
ttl: -1
|
|
108
|
+
})
|
|
109
|
+
)
|
|
110
|
+
),
|
|
111
|
+
Effect.provide(ctx),
|
|
112
|
+
Effect.orDie
|
|
113
|
+
)
|
|
114
|
+
}),
|
|
115
|
+
Effect.withLogSpan(`Cosmos.seedCheck ${name} in ${ns} [effect-app/infra/Store]`),
|
|
116
|
+
Effect.withSpan("Cosmos.seed [effect-app/infra/Store]", { attributes: { name, namespace: ns } })
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
const seedNamespace = Effect.fn("seedNamespace")(function*(ns: string) {
|
|
120
|
+
if (!seed) return
|
|
121
|
+
let cached = seedCache.get(ns)
|
|
122
|
+
if (!cached) {
|
|
123
|
+
cached = yield* Effect.cached(Effect.uninterruptible(makeSeedEffect(ns)))
|
|
124
|
+
seedCache.set(ns, cached)
|
|
125
|
+
}
|
|
126
|
+
yield* cached
|
|
127
|
+
})
|
|
128
|
+
const bulkSetInternal = (items: NonEmptyReadonlyArray<PM>, ns: string) =>
|
|
129
|
+
Effect
|
|
130
|
+
.gen(function*() {
|
|
131
|
+
// TODO: disable batching if need atomicity
|
|
132
|
+
// we delay and batch to keep low amount of RUs
|
|
133
|
+
const b = [...items]
|
|
134
|
+
.map(
|
|
135
|
+
(x) =>
|
|
136
|
+
[
|
|
137
|
+
x,
|
|
138
|
+
Option.match(Option.fromNullishOr(x._etag), {
|
|
139
|
+
onNone: () =>
|
|
140
|
+
dropUndefinedT({
|
|
141
|
+
operationType: "Create" as const,
|
|
142
|
+
resourceBody: {
|
|
143
|
+
...Struct.omit(x, ["_etag", idKey]),
|
|
144
|
+
id: x[idKey],
|
|
145
|
+
_partitionKey: nsPartitionValue(ns, x)
|
|
146
|
+
}
|
|
147
|
+
// don't use this or we get an error that the request and some item partition key dont match - makese no sense
|
|
148
|
+
// partitionKey: config?.partitionValue(x)
|
|
149
|
+
}),
|
|
150
|
+
onSome: (eTag) =>
|
|
151
|
+
dropUndefinedT({
|
|
152
|
+
operationType: "Replace" as const,
|
|
153
|
+
id: x[idKey],
|
|
154
|
+
resourceBody: {
|
|
155
|
+
...Struct.omit(x, ["_etag", idKey]),
|
|
156
|
+
id: x[idKey],
|
|
157
|
+
_partitionKey: nsPartitionValue(ns, x)
|
|
158
|
+
},
|
|
159
|
+
ifMatch: eTag
|
|
160
|
+
// don't use this or we get an error that the request and some item partition key dont match - makese no sense
|
|
161
|
+
// partitionKey: config?.partitionValue(x)
|
|
162
|
+
})
|
|
163
|
+
})
|
|
164
|
+
] as const
|
|
165
|
+
)
|
|
166
|
+
const batches = Array.chunksOf(b, config?.maxBulkSize ?? 10)
|
|
102
167
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
168
|
+
const batchResult = yield* Effect.forEach(
|
|
169
|
+
batches
|
|
170
|
+
.map((x, i) => [i, x] as const),
|
|
171
|
+
([i, batch]) =>
|
|
172
|
+
Effect
|
|
173
|
+
.promise(() => bulk(batch.map(([, op]) => op)))
|
|
174
|
+
.pipe(
|
|
107
175
|
Effect
|
|
108
|
-
.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
code: r.statusCode,
|
|
125
|
-
raw: responses
|
|
126
|
-
}
|
|
127
|
-
)
|
|
128
|
-
)
|
|
129
|
-
}
|
|
130
|
-
const r2 = responses.find(
|
|
131
|
-
(x) => x.statusCode !== 424 && (x.statusCode > 299 || x.statusCode < 200)
|
|
176
|
+
.delay(Duration.millis(i === 0 ? 0 : 150)),
|
|
177
|
+
Effect
|
|
178
|
+
.flatMap((responses) =>
|
|
179
|
+
Effect.gen(function*() {
|
|
180
|
+
const r = responses.find((x) =>
|
|
181
|
+
x.statusCode === 412 || x.statusCode === 404 || x.statusCode === 409
|
|
182
|
+
)
|
|
183
|
+
if (r) {
|
|
184
|
+
return yield* Effect.fail(
|
|
185
|
+
new OptimisticConcurrencyException(
|
|
186
|
+
{
|
|
187
|
+
type: name,
|
|
188
|
+
id: JSON.stringify(r.resourceBody?.["id"]),
|
|
189
|
+
code: r.statusCode,
|
|
190
|
+
raw: responses
|
|
191
|
+
}
|
|
132
192
|
)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
const r2 = responses.find(
|
|
196
|
+
(x) => x.statusCode !== 424 && (x.statusCode > 299 || x.statusCode < 200)
|
|
197
|
+
)
|
|
198
|
+
if (r2) {
|
|
199
|
+
return yield* Effect.die(
|
|
200
|
+
new CosmosDbOperationError(
|
|
201
|
+
"not able to update records: " + r2.statusCode,
|
|
202
|
+
responses
|
|
143
203
|
)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
responses
|
|
149
|
-
)
|
|
150
|
-
)
|
|
151
|
-
}
|
|
152
|
-
return batch.map(([e], i) => ({
|
|
153
|
-
...e,
|
|
154
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
155
|
-
_etag: responses[i]!.eTag
|
|
156
|
-
}))
|
|
157
|
-
})
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
const r3 = responses.find(
|
|
207
|
+
(x) => x.statusCode > 299 || x.statusCode < 200
|
|
158
208
|
)
|
|
209
|
+
if (r3) {
|
|
210
|
+
return yield* Effect.die(
|
|
211
|
+
new CosmosDbOperationError(
|
|
212
|
+
"not able to update records: " + r3.statusCode,
|
|
213
|
+
responses
|
|
214
|
+
)
|
|
215
|
+
)
|
|
216
|
+
}
|
|
217
|
+
return batch.map(([e], i) => ({
|
|
218
|
+
...e,
|
|
219
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
220
|
+
_etag: responses[i]!.eTag
|
|
221
|
+
}))
|
|
222
|
+
})
|
|
159
223
|
)
|
|
160
|
-
|
|
224
|
+
)
|
|
225
|
+
)
|
|
161
226
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
227
|
+
return batchResult.flat() as unknown as NonEmptyReadonlyArray<Encoded>
|
|
228
|
+
})
|
|
229
|
+
.pipe(
|
|
230
|
+
Effect.withSpan("Cosmos.bulkSet [effect-app/infra/Store]", {
|
|
231
|
+
attributes: { "repository.container_id": containerId, "repository.model_name": name, namespace: ns }
|
|
232
|
+
}, { captureStackTrace: false })
|
|
233
|
+
)
|
|
167
234
|
|
|
168
|
-
|
|
169
|
-
|
|
235
|
+
const bulkSet = (items: NonEmptyReadonlyArray<PM>) =>
|
|
236
|
+
resolveNamespace.pipe(Effect.flatMap((ns) => bulkSetInternal(items, ns)))
|
|
237
|
+
|
|
238
|
+
const batchSet = (items: NonEmptyReadonlyArray<PM>) => {
|
|
239
|
+
return resolveNamespace
|
|
240
|
+
.pipe(Effect.flatMap((ns) =>
|
|
241
|
+
Effect
|
|
170
242
|
.suspend(() => {
|
|
171
243
|
const batch = [...items].map(
|
|
172
244
|
(x) =>
|
|
@@ -178,7 +250,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
|
|
|
178
250
|
resourceBody: {
|
|
179
251
|
...Struct.omit(x, ["_etag", idKey]),
|
|
180
252
|
id: x[idKey],
|
|
181
|
-
_partitionKey:
|
|
253
|
+
_partitionKey: nsPartitionValue(ns, x)
|
|
182
254
|
}
|
|
183
255
|
// don't use this or we get an error that the request and some item partition key dont match - makese no sense
|
|
184
256
|
// partitionKey: config?.partitionValue(x)
|
|
@@ -189,7 +261,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
|
|
|
189
261
|
resourceBody: {
|
|
190
262
|
...Struct.omit(x, ["_etag", idKey]),
|
|
191
263
|
id: x[idKey],
|
|
192
|
-
_partitionKey:
|
|
264
|
+
_partitionKey: nsPartitionValue(ns, x)
|
|
193
265
|
},
|
|
194
266
|
// don't use this or we get an error that the request and some item partition key dont match - makese no sense
|
|
195
267
|
// partitionKey: config?.partitionValue(x)
|
|
@@ -227,36 +299,51 @@ function makeCosmosStore({ prefix }: StorageConfig) {
|
|
|
227
299
|
})
|
|
228
300
|
.pipe(Effect
|
|
229
301
|
.withSpan("Cosmos.batchSet [effect-app/infra/Store]", {
|
|
230
|
-
attributes: {
|
|
302
|
+
attributes: {
|
|
303
|
+
"repository.container_id": containerId,
|
|
304
|
+
"repository.model_name": name,
|
|
305
|
+
namespace: ns
|
|
306
|
+
}
|
|
231
307
|
}, { captureStackTrace: false }))
|
|
232
|
-
|
|
308
|
+
))
|
|
309
|
+
}
|
|
233
310
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
311
|
+
const s: Store<IdKey, Encoded> = {
|
|
312
|
+
seedNamespace: (ns) => seedNamespace(ns),
|
|
313
|
+
|
|
314
|
+
queryRaw: <Out>(query: RawQuery<Encoded, Out>) =>
|
|
315
|
+
Effect
|
|
316
|
+
.all({ q: Effect.sync(() => query.cosmos({ name })), ns: resolveNamespace })
|
|
317
|
+
.pipe(
|
|
318
|
+
Effect.tap(({ q }) => logQuery(q)),
|
|
319
|
+
Effect.flatMap(({ ns, q }) =>
|
|
320
|
+
Effect
|
|
321
|
+
.promise(() =>
|
|
322
|
+
container
|
|
323
|
+
.items
|
|
324
|
+
.query<Out>(q, { partitionKey: nsBasePartitionKey(ns) })
|
|
325
|
+
.fetchAll()
|
|
326
|
+
.then(({ resources }) =>
|
|
327
|
+
resources.map(
|
|
328
|
+
(_) => ({ ...defaultValues, ...mapReverseId(_ as any) }) as Out
|
|
250
329
|
)
|
|
251
|
-
|
|
252
|
-
)
|
|
253
|
-
|
|
254
|
-
.withSpan("Cosmos.queryRaw [effect-app/infra/Store]", {
|
|
255
|
-
attributes: {
|
|
330
|
+
)
|
|
331
|
+
)
|
|
332
|
+
.pipe(
|
|
333
|
+
Effect.withSpan("Cosmos.queryRaw [effect-app/infra/Store]", {
|
|
334
|
+
attributes: {
|
|
335
|
+
"repository.container_id": containerId,
|
|
336
|
+
"repository.model_name": name,
|
|
337
|
+
namespace: ns
|
|
338
|
+
}
|
|
256
339
|
}, { captureStackTrace: false })
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
340
|
+
)
|
|
341
|
+
)
|
|
342
|
+
),
|
|
343
|
+
batchRemove: (ids, partitionKey?: string) =>
|
|
344
|
+
resolveNamespace.pipe(Effect.flatMap((ns) =>
|
|
345
|
+
Effect
|
|
346
|
+
.promise(() =>
|
|
260
347
|
execBatch(
|
|
261
348
|
mutable(ids.map((id) =>
|
|
262
349
|
dropUndefinedT({
|
|
@@ -266,208 +353,215 @@ function makeCosmosStore({ prefix }: StorageConfig) {
|
|
|
266
353
|
// partitionKey: config?.partitionValue({ [idKey]: id } as Encoded)
|
|
267
354
|
})
|
|
268
355
|
)),
|
|
269
|
-
partitionKey ??
|
|
356
|
+
partitionKey ?? nsBasePartitionKey(ns)
|
|
270
357
|
)
|
|
271
|
-
)
|
|
272
|
-
all: Effect
|
|
273
|
-
.sync(() => ({
|
|
274
|
-
query: `SELECT * FROM ${name}`,
|
|
275
|
-
parameters: []
|
|
276
|
-
}))
|
|
358
|
+
)
|
|
277
359
|
.pipe(
|
|
278
|
-
Effect.
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
* May return duplicate results for "join_find", when matching more than once.
|
|
299
|
-
*/
|
|
300
|
-
filter: <U extends keyof Encoded = never>(
|
|
301
|
-
f: FilterArgs<Encoded, U>
|
|
302
|
-
) => {
|
|
303
|
-
const skip = f?.skip
|
|
304
|
-
const limit = f?.limit
|
|
305
|
-
const filter = f.filter
|
|
306
|
-
type M = U extends undefined ? Encoded : Pick<Encoded, U>
|
|
307
|
-
return Effect
|
|
308
|
-
.sync(() =>
|
|
309
|
-
buildWhereCosmosQuery3(
|
|
310
|
-
idKey,
|
|
311
|
-
filter ? [{ t: "where-scope", result: filter, relation: "some" }] : [],
|
|
312
|
-
name,
|
|
313
|
-
defaultValues,
|
|
314
|
-
f.select as NonEmptyReadonlyArray<string | { key: string; subKeys: readonly string[] }> | undefined,
|
|
315
|
-
f.order as NonEmptyReadonlyArray<{ key: string; direction: "ASC" | "DESC" }> | undefined,
|
|
316
|
-
skip,
|
|
317
|
-
limit
|
|
318
|
-
)
|
|
319
|
-
)
|
|
320
|
-
.pipe(
|
|
321
|
-
Effect.tap((q) => logQuery(q)),
|
|
322
|
-
Effect
|
|
323
|
-
.flatMap((q) =>
|
|
324
|
-
Effect.promise(() =>
|
|
325
|
-
f.select
|
|
326
|
-
? container
|
|
327
|
-
.items
|
|
328
|
-
.query<M>(q, { partitionKey: mainPartitionKey })
|
|
329
|
-
.fetchAll()
|
|
330
|
-
.then(({ resources }) =>
|
|
331
|
-
resources.map((_) => ({
|
|
332
|
-
...pipe(
|
|
333
|
-
defaultValues,
|
|
334
|
-
Struct.pick(f.select!.filter((_) => typeof _ === "string") as never[])
|
|
335
|
-
),
|
|
336
|
-
...mapReverseId(_ as any)
|
|
337
|
-
}))
|
|
338
|
-
)
|
|
339
|
-
: container
|
|
340
|
-
.items
|
|
341
|
-
.query<{ f: M }>(q, { partitionKey: mainPartitionKey })
|
|
342
|
-
.fetchAll()
|
|
343
|
-
.then(({ resources }) =>
|
|
344
|
-
resources.map(({ f }) => ({ ...defaultValues, ...mapReverseId(f as any) }) as any)
|
|
345
|
-
)
|
|
346
|
-
)
|
|
347
|
-
)
|
|
348
|
-
)
|
|
349
|
-
.pipe(
|
|
350
|
-
Effect.withSpan("Cosmos.filter [effect-app/infra/Store]", {
|
|
351
|
-
attributes: { "repository.container_id": containerId, "repository.model_name": name }
|
|
352
|
-
}, { captureStackTrace: false })
|
|
353
|
-
)
|
|
354
|
-
},
|
|
355
|
-
find: (id) =>
|
|
360
|
+
Effect.withSpan("Cosmos.batchRemove [effect-app/infra/Store]", {
|
|
361
|
+
attributes: {
|
|
362
|
+
"repository.container_id": containerId,
|
|
363
|
+
"repository.model_name": name,
|
|
364
|
+
namespace: ns
|
|
365
|
+
}
|
|
366
|
+
}, { captureStackTrace: false })
|
|
367
|
+
)
|
|
368
|
+
)),
|
|
369
|
+
all: Effect
|
|
370
|
+
.all({
|
|
371
|
+
q: Effect.sync(() => ({
|
|
372
|
+
query: `SELECT * FROM ${name}`,
|
|
373
|
+
parameters: []
|
|
374
|
+
})),
|
|
375
|
+
ns: resolveNamespace
|
|
376
|
+
})
|
|
377
|
+
.pipe(
|
|
378
|
+
Effect.tap(({ q }) => logQuery(q)),
|
|
379
|
+
Effect.flatMap(({ ns, q }) =>
|
|
356
380
|
Effect
|
|
357
381
|
.promise(() =>
|
|
358
382
|
container
|
|
359
|
-
.
|
|
360
|
-
.
|
|
361
|
-
.
|
|
362
|
-
|
|
383
|
+
.items
|
|
384
|
+
.query<PMCosmos>(q, { partitionKey: nsBasePartitionKey(ns) })
|
|
385
|
+
.fetchAll()
|
|
386
|
+
.then(({ resources }) =>
|
|
387
|
+
resources.map(
|
|
388
|
+
(_) => ({ ...defaultValues, ...mapReverseId(_) })
|
|
389
|
+
)
|
|
363
390
|
)
|
|
364
391
|
)
|
|
365
|
-
.pipe(
|
|
366
|
-
.withSpan("Cosmos.
|
|
392
|
+
.pipe(
|
|
393
|
+
Effect.withSpan("Cosmos.all [effect-app/infra/Store]", {
|
|
367
394
|
attributes: {
|
|
368
395
|
"repository.container_id": containerId,
|
|
369
396
|
"repository.model_name": name,
|
|
370
|
-
|
|
371
|
-
id
|
|
397
|
+
namespace: ns
|
|
372
398
|
}
|
|
373
|
-
}, { captureStackTrace: false })
|
|
374
|
-
set: (e) =>
|
|
375
|
-
Option
|
|
376
|
-
.match(
|
|
377
|
-
Option
|
|
378
|
-
.fromNullishOr(e._etag),
|
|
379
|
-
{
|
|
380
|
-
onNone: () =>
|
|
381
|
-
Effect.promise(() =>
|
|
382
|
-
container.items.create({
|
|
383
|
-
...mapId(e),
|
|
384
|
-
_partitionKey: config?.partitionValue(e)
|
|
385
|
-
})
|
|
386
|
-
),
|
|
387
|
-
onSome: (eTag) =>
|
|
388
|
-
Effect.promise(() =>
|
|
389
|
-
container.item(e[idKey], config?.partitionValue(e)).replace(
|
|
390
|
-
{ ...mapId(e), _partitionKey: config?.partitionValue(e) },
|
|
391
|
-
{
|
|
392
|
-
accessCondition: {
|
|
393
|
-
type: "IfMatch",
|
|
394
|
-
condition: eTag
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
)
|
|
398
|
-
)
|
|
399
|
-
}
|
|
399
|
+
}, { captureStackTrace: false })
|
|
400
400
|
)
|
|
401
|
-
|
|
401
|
+
)
|
|
402
|
+
),
|
|
403
|
+
/**
|
|
404
|
+
* May return duplicate results for "join_find", when matching more than once.
|
|
405
|
+
*/
|
|
406
|
+
filter: <U extends keyof Encoded = never>(
|
|
407
|
+
f: FilterArgs<Encoded, U>
|
|
408
|
+
) => {
|
|
409
|
+
const skip = f?.skip
|
|
410
|
+
const limit = f?.limit
|
|
411
|
+
const filter = f.filter
|
|
412
|
+
type M = U extends undefined ? Encoded : Pick<Encoded, U>
|
|
413
|
+
return Effect
|
|
414
|
+
.all({
|
|
415
|
+
q: Effect.sync(() =>
|
|
416
|
+
buildWhereCosmosQuery3(
|
|
417
|
+
idKey,
|
|
418
|
+
filter ? [{ t: "where-scope", result: filter, relation: "some" }] : [],
|
|
419
|
+
name,
|
|
420
|
+
defaultValues,
|
|
421
|
+
f.select as
|
|
422
|
+
| NonEmptyReadonlyArray<string | { key: string; subKeys: readonly string[] }>
|
|
423
|
+
| undefined,
|
|
424
|
+
f.order as NonEmptyReadonlyArray<{ key: string; direction: "ASC" | "DESC" }> | undefined,
|
|
425
|
+
skip,
|
|
426
|
+
limit
|
|
427
|
+
)
|
|
428
|
+
),
|
|
429
|
+
ns: resolveNamespace
|
|
430
|
+
})
|
|
431
|
+
.pipe(
|
|
432
|
+
Effect.tap(({ q }) => logQuery(q)),
|
|
433
|
+
Effect
|
|
434
|
+
.flatMap(({ ns, q }) =>
|
|
402
435
|
Effect
|
|
403
|
-
.
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
436
|
+
.promise(() =>
|
|
437
|
+
f.select
|
|
438
|
+
? container
|
|
439
|
+
.items
|
|
440
|
+
.query<M>(q, { partitionKey: nsBasePartitionKey(ns) })
|
|
441
|
+
.fetchAll()
|
|
442
|
+
.then(({ resources }) =>
|
|
443
|
+
resources.map((_) => ({
|
|
444
|
+
...pipe(
|
|
445
|
+
defaultValues,
|
|
446
|
+
Struct.pick(f.select!.filter((_) => typeof _ === "string") as never[])
|
|
447
|
+
),
|
|
448
|
+
...mapReverseId(_ as any)
|
|
449
|
+
}))
|
|
450
|
+
)
|
|
451
|
+
: container
|
|
452
|
+
.items
|
|
453
|
+
.query<{ f: M }>(q, { partitionKey: nsBasePartitionKey(ns) })
|
|
454
|
+
.fetchAll()
|
|
455
|
+
.then(({ resources }) =>
|
|
456
|
+
resources.map(({ f }) => ({ ...defaultValues, ...mapReverseId(f as any) }) as any)
|
|
413
457
|
)
|
|
458
|
+
)
|
|
459
|
+
.pipe(
|
|
460
|
+
Effect.withSpan("Cosmos.filter [effect-app/infra/Store]", {
|
|
461
|
+
attributes: {
|
|
462
|
+
"repository.container_id": containerId,
|
|
463
|
+
"repository.model_name": name,
|
|
464
|
+
namespace: ns
|
|
465
|
+
}
|
|
466
|
+
}, { captureStackTrace: false })
|
|
467
|
+
)
|
|
468
|
+
)
|
|
469
|
+
)
|
|
470
|
+
},
|
|
471
|
+
find: (id) =>
|
|
472
|
+
resolveNamespace.pipe(Effect.flatMap((ns) =>
|
|
473
|
+
Effect
|
|
474
|
+
.promise(() =>
|
|
475
|
+
container
|
|
476
|
+
.item(id, nsPartitionValue(ns, { [idKey]: id } as Encoded))
|
|
477
|
+
.read<Encoded>()
|
|
478
|
+
.then(({ resource }) =>
|
|
479
|
+
Option.fromNullishOr(resource).pipe(
|
|
480
|
+
Option.map((_) => ({ ...defaultValues, ...mapReverseId(_) }))
|
|
481
|
+
)
|
|
482
|
+
)
|
|
483
|
+
)
|
|
484
|
+
.pipe(Effect
|
|
485
|
+
.withSpan("Cosmos.find [effect-app/infra/Store]", {
|
|
486
|
+
attributes: {
|
|
487
|
+
"repository.container_id": containerId,
|
|
488
|
+
"repository.model_name": name,
|
|
489
|
+
partitionValue: nsPartitionValue(ns, { [idKey]: id } as Encoded),
|
|
490
|
+
namespace: ns,
|
|
491
|
+
id
|
|
492
|
+
}
|
|
493
|
+
}, { captureStackTrace: false }))
|
|
494
|
+
)),
|
|
495
|
+
set: (e) =>
|
|
496
|
+
resolveNamespace.pipe(Effect.flatMap((ns) =>
|
|
497
|
+
Option
|
|
498
|
+
.match(
|
|
499
|
+
Option
|
|
500
|
+
.fromNullishOr(e._etag),
|
|
501
|
+
{
|
|
502
|
+
onNone: () =>
|
|
503
|
+
Effect.promise(() =>
|
|
504
|
+
container.items.create({
|
|
505
|
+
...mapId(e),
|
|
506
|
+
_partitionKey: nsPartitionValue(ns, e)
|
|
507
|
+
})
|
|
508
|
+
),
|
|
509
|
+
onSome: (eTag) =>
|
|
510
|
+
Effect.promise(() =>
|
|
511
|
+
container.item(e[idKey], nsPartitionValue(ns, e)).replace(
|
|
512
|
+
{ ...mapId(e), _partitionKey: nsPartitionValue(ns, e) },
|
|
513
|
+
{
|
|
514
|
+
accessCondition: {
|
|
515
|
+
type: "IfMatch",
|
|
516
|
+
condition: eTag
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
)
|
|
520
|
+
)
|
|
521
|
+
}
|
|
522
|
+
)
|
|
523
|
+
.pipe(
|
|
524
|
+
Effect
|
|
525
|
+
.flatMap((x) => {
|
|
526
|
+
if (x.statusCode === 412 || x.statusCode === 404 || x.statusCode === 409) {
|
|
527
|
+
return Effect.fail(
|
|
528
|
+
new OptimisticConcurrencyException({ type: name, id: e[idKey], code: x.statusCode })
|
|
529
|
+
)
|
|
530
|
+
}
|
|
531
|
+
if (x.statusCode > 299 || x.statusCode < 200) {
|
|
532
|
+
return Effect.die(
|
|
533
|
+
new CosmosDbOperationError(
|
|
534
|
+
"not able to update record: " + x.statusCode
|
|
414
535
|
)
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
})
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
536
|
+
)
|
|
537
|
+
}
|
|
538
|
+
return Effect.sync(() => ({
|
|
539
|
+
...e,
|
|
540
|
+
_etag: x.etag
|
|
541
|
+
}))
|
|
542
|
+
}),
|
|
543
|
+
Effect
|
|
544
|
+
.withSpan("Cosmos.set [effect-app/infra/Store]", {
|
|
545
|
+
attributes: {
|
|
546
|
+
"repository.container_id": containerId,
|
|
547
|
+
"repository.model_name": name,
|
|
548
|
+
namespace: ns,
|
|
549
|
+
id: e[idKey]
|
|
550
|
+
}
|
|
551
|
+
}, { captureStackTrace: false })
|
|
552
|
+
)
|
|
553
|
+
)),
|
|
554
|
+
batchSet,
|
|
555
|
+
bulkSet
|
|
556
|
+
}
|
|
433
557
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
container
|
|
437
|
-
.item(importedMarkerId, importedMarkerId)
|
|
438
|
-
.read<{ id: string }>()
|
|
439
|
-
.then(({ resource }) => Option.fromNullishOr(resource))
|
|
440
|
-
)
|
|
558
|
+
// Eagerly seed primary namespace on initialization
|
|
559
|
+
yield* seedNamespace("primary")
|
|
441
560
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
yield* Effect.flatMapOption(
|
|
447
|
-
Effect.succeed(toNonEmptyArray([...m])),
|
|
448
|
-
(a) =>
|
|
449
|
-
s.bulkSet(a).pipe(
|
|
450
|
-
Effect.orDie,
|
|
451
|
-
Effect
|
|
452
|
-
// we delay extra here, so that initial creation between Companies/POs also have an interval between them.
|
|
453
|
-
.delay(Duration.millis(1100))
|
|
454
|
-
)
|
|
455
|
-
)
|
|
456
|
-
}
|
|
457
|
-
// Mark as imported
|
|
458
|
-
yield* Effect.promise(() =>
|
|
459
|
-
container.items.create({
|
|
460
|
-
_partitionKey: importedMarkerId,
|
|
461
|
-
id: importedMarkerId,
|
|
462
|
-
ttl: -1
|
|
463
|
-
})
|
|
464
|
-
)
|
|
465
|
-
}
|
|
466
|
-
return s
|
|
467
|
-
})
|
|
468
|
-
}
|
|
469
|
-
})
|
|
470
|
-
}
|
|
561
|
+
return s
|
|
562
|
+
})
|
|
563
|
+
}
|
|
564
|
+
})
|
|
471
565
|
|
|
472
566
|
export function CosmosStoreLayer(cfg: StorageConfig) {
|
|
473
567
|
return StoreMaker
|