dfx 1.0.5 → 1.0.7
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/dist/Cache/driver.d.ts.map +1 -1
- package/dist/Cache/memory.d.ts.map +1 -1
- package/dist/Cache/memoryTTL.d.ts.map +1 -1
- package/dist/Cache/prelude.d.ts.map +1 -1
- package/dist/Cache.d.ts.map +1 -1
- package/dist/DiscordConfig.d.ts.map +1 -1
- package/dist/DiscordGateway/DiscordWS.d.ts.map +1 -1
- package/dist/DiscordGateway/Messaging.d.ts.map +1 -1
- package/dist/DiscordGateway/Shard/StateStore.d.ts.map +1 -1
- package/dist/DiscordGateway/Shard/heartbeats.d.ts.map +1 -1
- package/dist/DiscordGateway/Shard/identify.d.ts.map +1 -1
- package/dist/DiscordGateway/Shard/sendEvents.d.ts.map +1 -1
- package/dist/DiscordGateway/Shard/utils.d.ts.map +1 -1
- package/dist/DiscordGateway/Shard.d.ts.map +1 -1
- package/dist/DiscordGateway/ShardStore.d.ts.map +1 -1
- package/dist/DiscordGateway/Sharder.d.ts +1 -1
- package/dist/DiscordGateway/Sharder.d.ts.map +1 -1
- package/dist/DiscordGateway.d.ts.map +1 -1
- package/dist/DiscordREST/Generated.d.ts.map +1 -1
- package/dist/DiscordREST/utils.d.ts.map +1 -1
- package/dist/DiscordREST.d.ts.map +1 -1
- package/dist/Helpers/flags.d.ts.map +1 -1
- package/dist/Helpers/intents.d.ts.map +1 -1
- package/dist/Helpers/interactions.d.ts.map +1 -1
- package/dist/Helpers/members.d.ts.map +1 -1
- package/dist/Helpers/permissions.d.ts.map +1 -1
- package/dist/Helpers/ui.d.ts.map +1 -1
- package/dist/Interactions/builder.d.ts.map +1 -1
- package/dist/Interactions/commandHelper.d.ts.map +1 -1
- package/dist/Interactions/context.d.ts.map +1 -1
- package/dist/Interactions/definitions.d.ts.map +1 -1
- package/dist/Interactions/error.d.ts.map +1 -1
- package/dist/Interactions/gateway.d.ts.map +1 -1
- package/dist/Interactions/handlers.d.ts.map +1 -1
- package/dist/Interactions/index.d.ts.map +1 -1
- package/dist/Interactions/utils.d.ts.map +1 -1
- package/dist/Interactions/webhook.d.ts.map +1 -1
- package/dist/RateLimit/memory.d.ts.map +1 -1
- package/dist/RateLimit/utils.d.ts.map +1 -1
- package/dist/RateLimit.d.ts.map +1 -1
- package/dist/gateway.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/Effect.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/webhooks.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/version.ts +1 -1
- package/dist/LICENSE +0 -21
- package/dist/README.md +0 -66
- package/dist/mjs/Cache/driver.mjs +0 -3
- package/dist/mjs/Cache/driver.mjs.map +0 -1
- package/dist/mjs/Cache/memory.mjs +0 -48
- package/dist/mjs/Cache/memory.mjs.map +0 -1
- package/dist/mjs/Cache/memoryTTL.mjs +0 -119
- package/dist/mjs/Cache/memoryTTL.mjs.map +0 -1
- package/dist/mjs/Cache/prelude.mjs +0 -131
- package/dist/mjs/Cache/prelude.mjs.map +0 -1
- package/dist/mjs/Cache.mjs +0 -90
- package/dist/mjs/Cache.mjs.map +0 -1
- package/dist/mjs/DiscordConfig.mjs +0 -32
- package/dist/mjs/DiscordConfig.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/DiscordWS.mjs +0 -77
- package/dist/mjs/DiscordGateway/DiscordWS.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Messaging.mjs +0 -35
- package/dist/mjs/DiscordGateway/Messaging.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Shard/StateStore.mjs +0 -41
- package/dist/mjs/DiscordGateway/Shard/StateStore.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Shard/heartbeats.mjs +0 -25
- package/dist/mjs/DiscordGateway/Shard/heartbeats.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Shard/identify.mjs +0 -29
- package/dist/mjs/DiscordGateway/Shard/identify.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Shard/sendEvents.mjs +0 -26
- package/dist/mjs/DiscordGateway/Shard/sendEvents.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Shard/utils.mjs +0 -3
- package/dist/mjs/DiscordGateway/Shard/utils.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Shard.mjs +0 -147
- package/dist/mjs/DiscordGateway/Shard.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/ShardStore.mjs +0 -24
- package/dist/mjs/DiscordGateway/ShardStore.mjs.map +0 -1
- package/dist/mjs/DiscordGateway/Sharder.mjs +0 -67
- package/dist/mjs/DiscordGateway/Sharder.mjs.map +0 -1
- package/dist/mjs/DiscordGateway.mjs +0 -21
- package/dist/mjs/DiscordGateway.mjs.map +0 -1
- package/dist/mjs/DiscordREST/Generated.mjs +0 -2471
- package/dist/mjs/DiscordREST/Generated.mjs.map +0 -1
- package/dist/mjs/DiscordREST/utils.mjs +0 -21
- package/dist/mjs/DiscordREST/utils.mjs.map +0 -1
- package/dist/mjs/DiscordREST.mjs +0 -119
- package/dist/mjs/DiscordREST.mjs.map +0 -1
- package/dist/mjs/Helpers/flags.mjs +0 -45
- package/dist/mjs/Helpers/flags.mjs.map +0 -1
- package/dist/mjs/Helpers/intents.mjs +0 -27
- package/dist/mjs/Helpers/intents.mjs.map +0 -1
- package/dist/mjs/Helpers/interactions.mjs +0 -115
- package/dist/mjs/Helpers/interactions.mjs.map +0 -1
- package/dist/mjs/Helpers/members.mjs +0 -9
- package/dist/mjs/Helpers/members.mjs.map +0 -1
- package/dist/mjs/Helpers/permissions.mjs +0 -84
- package/dist/mjs/Helpers/permissions.mjs.map +0 -1
- package/dist/mjs/Helpers/ui.mjs +0 -137
- package/dist/mjs/Helpers/ui.mjs.map +0 -1
- package/dist/mjs/Interactions/builder.mjs +0 -56
- package/dist/mjs/Interactions/builder.mjs.map +0 -1
- package/dist/mjs/Interactions/commandHelper.mjs +0 -49
- package/dist/mjs/Interactions/commandHelper.mjs.map +0 -1
- package/dist/mjs/Interactions/context.mjs +0 -28
- package/dist/mjs/Interactions/context.mjs.map +0 -1
- package/dist/mjs/Interactions/definitions.mjs +0 -51
- package/dist/mjs/Interactions/definitions.mjs.map +0 -1
- package/dist/mjs/Interactions/error.mjs +0 -2
- package/dist/mjs/Interactions/error.mjs.map +0 -1
- package/dist/mjs/Interactions/gateway.mjs +0 -82
- package/dist/mjs/Interactions/gateway.mjs.map +0 -1
- package/dist/mjs/Interactions/handlers.mjs +0 -64
- package/dist/mjs/Interactions/handlers.mjs.map +0 -1
- package/dist/mjs/Interactions/index.mjs +0 -11
- package/dist/mjs/Interactions/index.mjs.map +0 -1
- package/dist/mjs/Interactions/utils.mjs +0 -26
- package/dist/mjs/Interactions/utils.mjs.map +0 -1
- package/dist/mjs/Interactions/webhook.mjs +0 -75
- package/dist/mjs/Interactions/webhook.mjs.map +0 -1
- package/dist/mjs/RateLimit/memory.mjs +0 -39
- package/dist/mjs/RateLimit/memory.mjs.map +0 -1
- package/dist/mjs/RateLimit/utils.mjs +0 -18
- package/dist/mjs/RateLimit/utils.mjs.map +0 -1
- package/dist/mjs/RateLimit.mjs +0 -28
- package/dist/mjs/RateLimit.mjs.map +0 -1
- package/dist/mjs/gateway.mjs +0 -19
- package/dist/mjs/gateway.mjs.map +0 -1
- package/dist/mjs/index.mjs +0 -18
- package/dist/mjs/index.mjs.map +0 -1
- package/dist/mjs/types.mjs +0 -356
- package/dist/mjs/types.mjs.map +0 -1
- package/dist/mjs/utils/Effect.mjs +0 -44
- package/dist/mjs/utils/Effect.mjs.map +0 -1
- package/dist/mjs/version.mjs +0 -2
- package/dist/mjs/version.mjs.map +0 -1
- package/dist/mjs/webhooks.mjs +0 -6
- package/dist/mjs/webhooks.mjs.map +0 -1
- package/dist/package.json +0 -48
- package/dist/src/Cache/driver.ts +0 -37
- package/dist/src/Cache/memory.ts +0 -83
- package/dist/src/Cache/memoryTTL.ts +0 -225
- package/dist/src/Cache/prelude.ts +0 -279
- package/dist/src/Cache.ts +0 -261
- package/dist/src/DiscordConfig.ts +0 -67
- package/dist/src/DiscordGateway/DiscordWS.ts +0 -157
- package/dist/src/DiscordGateway/Messaging.ts +0 -71
- package/dist/src/DiscordGateway/Shard/StateStore.ts +0 -72
- package/dist/src/DiscordGateway/Shard/heartbeats.ts +0 -60
- package/dist/src/DiscordGateway/Shard/identify.ts +0 -50
- package/dist/src/DiscordGateway/Shard/sendEvents.ts +0 -43
- package/dist/src/DiscordGateway/Shard/utils.ts +0 -13
- package/dist/src/DiscordGateway/Shard.ts +0 -205
- package/dist/src/DiscordGateway/ShardStore.ts +0 -42
- package/dist/src/DiscordGateway/Sharder.ts +0 -118
- package/dist/src/DiscordGateway.ts +0 -79
- package/dist/src/DiscordREST/Generated.ts +0 -10832
- package/dist/src/DiscordREST/utils.ts +0 -42
- package/dist/src/DiscordREST.ts +0 -256
- package/dist/src/Helpers/flags.ts +0 -73
- package/dist/src/Helpers/intents.ts +0 -35
- package/dist/src/Helpers/interactions.ts +0 -317
- package/dist/src/Helpers/members.ts +0 -18
- package/dist/src/Helpers/permissions.ts +0 -145
- package/dist/src/Helpers/ui.ts +0 -253
- package/dist/src/Interactions/builder.ts +0 -171
- package/dist/src/Interactions/commandHelper.ts +0 -231
- package/dist/src/Interactions/context.ts +0 -104
- package/dist/src/Interactions/definitions.ts +0 -144
- package/dist/src/Interactions/error.ts +0 -3
- package/dist/src/Interactions/gateway.ts +0 -193
- package/dist/src/Interactions/handlers.ts +0 -108
- package/dist/src/Interactions/index.ts +0 -30
- package/dist/src/Interactions/utils.ts +0 -93
- package/dist/src/Interactions/webhook.ts +0 -204
- package/dist/src/RateLimit/memory.ts +0 -63
- package/dist/src/RateLimit/utils.ts +0 -28
- package/dist/src/RateLimit.ts +0 -90
- package/dist/src/gateway.ts +0 -50
- package/dist/src/index.ts +0 -44
- package/dist/src/types.ts +0 -3090
- package/dist/src/utils/Effect.ts +0 -65
- package/dist/src/version.ts +0 -1
- package/dist/src/webhooks.ts +0 -25
- package/dist/tsconfig.base.json +0 -54
- package/dist/tsconfig.build.json +0 -10
- package/dist/tsconfig.examples.json +0 -10
- package/dist/tsconfig.json +0 -14
- package/dist/tsconfig.madge.json +0 -12
- package/dist/tsconfig.test.json +0 -10
package/dist/src/Cache.ts
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
import type { CacheDriver, ParentCacheDriver } from "./Cache/driver.ts"
|
|
2
|
-
import * as Data from "effect/Data"
|
|
3
|
-
import * as Effect from "effect/Effect"
|
|
4
|
-
import * as Option from "effect/Option"
|
|
5
|
-
import * as Schedule from "effect/Schedule"
|
|
6
|
-
import type * as Scope from "effect/Scope"
|
|
7
|
-
import * as Stream from "effect/Stream"
|
|
8
|
-
|
|
9
|
-
export * from "./Cache/driver.ts"
|
|
10
|
-
export {
|
|
11
|
-
create as memoryDriver,
|
|
12
|
-
createWithParent as memoryParentDriver,
|
|
13
|
-
} from "./Cache/memory.ts"
|
|
14
|
-
export {
|
|
15
|
-
create as memoryTTLDriver,
|
|
16
|
-
createWithParent as memoryTTLParentDriver,
|
|
17
|
-
} from "./Cache/memoryTTL.ts"
|
|
18
|
-
|
|
19
|
-
export type ParentCacheOp<T> =
|
|
20
|
-
| { op: "create"; parentId: string; resourceId: string; resource: T }
|
|
21
|
-
| { op: "update"; parentId: string; resourceId: string; resource: T }
|
|
22
|
-
| { op: "delete"; parentId: string; resourceId: string }
|
|
23
|
-
| { op: "parentDelete"; parentId: string }
|
|
24
|
-
|
|
25
|
-
export type CacheOp<T> =
|
|
26
|
-
| { op: "create"; resourceId: string; resource: T }
|
|
27
|
-
| { op: "update"; resourceId: string; resource: T }
|
|
28
|
-
| { op: "delete"; resourceId: string }
|
|
29
|
-
|
|
30
|
-
const retryPolicy = Schedule.exponential("500 millis").pipe(
|
|
31
|
-
Schedule.either(Schedule.spaced("10 seconds")),
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
export interface ParentCache<EDriver, EMiss, EPMiss, A> {
|
|
35
|
-
readonly get: (
|
|
36
|
-
parentId: string,
|
|
37
|
-
id: string,
|
|
38
|
-
) => Effect.Effect<A, EDriver | EMiss>
|
|
39
|
-
readonly put: (_: A) => Effect.Effect<void, EDriver | EMiss>
|
|
40
|
-
readonly update: <R, E>(
|
|
41
|
-
parentId: string,
|
|
42
|
-
id: string,
|
|
43
|
-
f: (_: A) => Effect.Effect<A, E, R>,
|
|
44
|
-
) => Effect.Effect<A, EDriver | EMiss | E, R>
|
|
45
|
-
readonly getForParent: (
|
|
46
|
-
parentId: string,
|
|
47
|
-
) => Effect.Effect<ReadonlyMap<string, A>, EDriver | EPMiss>
|
|
48
|
-
readonly size: Effect.Effect<number, EDriver>
|
|
49
|
-
readonly sizeForParent: (parentId: string) => Effect.Effect<number, EDriver>
|
|
50
|
-
readonly set: (
|
|
51
|
-
parentId: string,
|
|
52
|
-
resourceId: string,
|
|
53
|
-
resource: A,
|
|
54
|
-
) => Effect.Effect<void, EDriver>
|
|
55
|
-
readonly delete: (
|
|
56
|
-
parentId: string,
|
|
57
|
-
resourceId: string,
|
|
58
|
-
) => Effect.Effect<void, EDriver>
|
|
59
|
-
readonly parentDelete: (parentId: string) => Effect.Effect<void, EDriver>
|
|
60
|
-
readonly refreshTTL: (
|
|
61
|
-
parentId: string,
|
|
62
|
-
resourceId: string,
|
|
63
|
-
) => Effect.Effect<void, EDriver>
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export const makeWithParent = <EOps, EDriver, EMiss, EPMiss, A>({
|
|
67
|
-
driver,
|
|
68
|
-
id: identify,
|
|
69
|
-
onMiss,
|
|
70
|
-
onParentMiss,
|
|
71
|
-
ops = Stream.empty,
|
|
72
|
-
}: {
|
|
73
|
-
driver: ParentCacheDriver<EDriver, A>
|
|
74
|
-
ops?: Stream.Stream<ParentCacheOp<A>, EOps>
|
|
75
|
-
id: (_: A) => Effect.Effect<readonly [parentId: string, id: string], EMiss>
|
|
76
|
-
onMiss: (parentId: string, id: string) => Effect.Effect<A, EMiss>
|
|
77
|
-
onParentMiss: (
|
|
78
|
-
parentId: string,
|
|
79
|
-
) => Effect.Effect<Array<readonly [id: string, resource: A]>, EPMiss>
|
|
80
|
-
}): Effect.Effect<ParentCache<EDriver, EMiss, EPMiss, A>, never, Scope.Scope> =>
|
|
81
|
-
Effect.gen(function* () {
|
|
82
|
-
yield* Stream.runDrain(
|
|
83
|
-
Stream.tap(ops, (op): Effect.Effect<void, EDriver> => {
|
|
84
|
-
switch (op.op) {
|
|
85
|
-
case "create":
|
|
86
|
-
case "update":
|
|
87
|
-
return driver.set(op.parentId, op.resourceId, op.resource)
|
|
88
|
-
|
|
89
|
-
case "delete":
|
|
90
|
-
return driver.delete(op.parentId, op.resourceId)
|
|
91
|
-
|
|
92
|
-
case "parentDelete":
|
|
93
|
-
return driver.parentDelete(op.parentId)
|
|
94
|
-
}
|
|
95
|
-
}),
|
|
96
|
-
).pipe(
|
|
97
|
-
Effect.tapCause(cause => Effect.logError("ops error, restarting", cause)),
|
|
98
|
-
Effect.retry(retryPolicy),
|
|
99
|
-
Effect.forkScoped,
|
|
100
|
-
Effect.interruptible,
|
|
101
|
-
)
|
|
102
|
-
yield* driver.run.pipe(
|
|
103
|
-
Effect.tapCause(cause =>
|
|
104
|
-
Effect.logError("cache driver error, restarting", cause),
|
|
105
|
-
),
|
|
106
|
-
Effect.retry(retryPolicy),
|
|
107
|
-
Effect.forkScoped,
|
|
108
|
-
Effect.interruptible,
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
const get = (parentId: string, id: string) =>
|
|
112
|
-
Effect.flatMap(driver.get(parentId, id), option =>
|
|
113
|
-
Option.match(option, {
|
|
114
|
-
onNone: () =>
|
|
115
|
-
Effect.tap(onMiss(parentId, id), a => driver.set(parentId, id, a)),
|
|
116
|
-
onSome: Effect.succeed,
|
|
117
|
-
}),
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
const put = (_: A) =>
|
|
121
|
-
Effect.flatMap(identify(_), ([parentId, id]) =>
|
|
122
|
-
driver.set(parentId, id, _),
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
const update = <R, E>(
|
|
126
|
-
parentId: string,
|
|
127
|
-
id: string,
|
|
128
|
-
f: (_: A) => Effect.Effect<A, E, R>,
|
|
129
|
-
) =>
|
|
130
|
-
Effect.flatMap(get(parentId, id), a =>
|
|
131
|
-
Effect.tap(f(a), next => driver.set(parentId, id, next)),
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
return {
|
|
135
|
-
...driver,
|
|
136
|
-
|
|
137
|
-
get,
|
|
138
|
-
put,
|
|
139
|
-
update,
|
|
140
|
-
|
|
141
|
-
getForParent: (parentId: string) =>
|
|
142
|
-
Effect.flatMap(driver.getForParent(parentId), option =>
|
|
143
|
-
Option.match(option, {
|
|
144
|
-
onNone: () =>
|
|
145
|
-
onParentMiss(parentId).pipe(
|
|
146
|
-
Effect.tap(entries =>
|
|
147
|
-
Effect.all(
|
|
148
|
-
entries.map(([id, a]) => driver.set(parentId, id, a)),
|
|
149
|
-
{ concurrency: "unbounded" },
|
|
150
|
-
),
|
|
151
|
-
),
|
|
152
|
-
Effect.map(
|
|
153
|
-
entries => new Map(entries) as ReadonlyMap<string, A>,
|
|
154
|
-
),
|
|
155
|
-
),
|
|
156
|
-
onSome: Effect.succeed,
|
|
157
|
-
}),
|
|
158
|
-
),
|
|
159
|
-
} as const
|
|
160
|
-
}).pipe(
|
|
161
|
-
Effect.annotateLogs({
|
|
162
|
-
package: "dfx",
|
|
163
|
-
service: "Cache",
|
|
164
|
-
}),
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
export interface Cache<EDriver, EMiss, A> {
|
|
168
|
-
readonly get: (id: string) => Effect.Effect<A, EDriver | EMiss>
|
|
169
|
-
readonly put: (_: A) => Effect.Effect<void, EDriver>
|
|
170
|
-
readonly update: <R, E>(
|
|
171
|
-
id: string,
|
|
172
|
-
f: (_: A) => Effect.Effect<A, E, R>,
|
|
173
|
-
) => Effect.Effect<A, EDriver | EMiss | E, R>
|
|
174
|
-
readonly size: Effect.Effect<number, EDriver>
|
|
175
|
-
readonly set: (
|
|
176
|
-
resourceId: string,
|
|
177
|
-
resource: A,
|
|
178
|
-
) => Effect.Effect<void, EDriver>
|
|
179
|
-
readonly delete: (resourceId: string) => Effect.Effect<void, EDriver>
|
|
180
|
-
readonly refreshTTL: (resourceId: string) => Effect.Effect<void, EDriver>
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export const make = <EOps, EDriver, EMiss, A>({
|
|
184
|
-
driver,
|
|
185
|
-
id: identify,
|
|
186
|
-
onMiss,
|
|
187
|
-
ops = Stream.empty,
|
|
188
|
-
}: {
|
|
189
|
-
driver: CacheDriver<EDriver, A>
|
|
190
|
-
ops?: Stream.Stream<CacheOp<A>, EOps>
|
|
191
|
-
id: (_: A) => string
|
|
192
|
-
onMiss: (id: string) => Effect.Effect<A, EMiss>
|
|
193
|
-
}): Effect.Effect<Cache<EDriver, EMiss, A>, never, Scope.Scope> =>
|
|
194
|
-
Effect.gen(function* () {
|
|
195
|
-
yield* Stream.runDrain(
|
|
196
|
-
Stream.tap(ops, (op): Effect.Effect<void, EDriver> => {
|
|
197
|
-
switch (op.op) {
|
|
198
|
-
case "create":
|
|
199
|
-
case "update":
|
|
200
|
-
return driver.set(op.resourceId, op.resource)
|
|
201
|
-
|
|
202
|
-
case "delete":
|
|
203
|
-
return driver.delete(op.resourceId)
|
|
204
|
-
}
|
|
205
|
-
}),
|
|
206
|
-
).pipe(
|
|
207
|
-
Effect.tapCause(cause => Effect.logError("ops error, restarting", cause)),
|
|
208
|
-
Effect.retry(retryPolicy),
|
|
209
|
-
Effect.forkScoped,
|
|
210
|
-
Effect.interruptible,
|
|
211
|
-
)
|
|
212
|
-
|
|
213
|
-
yield* driver.run.pipe(
|
|
214
|
-
Effect.tapCause(cause =>
|
|
215
|
-
Effect.logError("cache driver error, restarting", cause),
|
|
216
|
-
),
|
|
217
|
-
Effect.retry(retryPolicy),
|
|
218
|
-
Effect.forkScoped,
|
|
219
|
-
Effect.interruptible,
|
|
220
|
-
)
|
|
221
|
-
|
|
222
|
-
const get = (id: string) =>
|
|
223
|
-
Effect.flatMap(driver.get(id), option =>
|
|
224
|
-
Option.match(option, {
|
|
225
|
-
onNone: () => Effect.tap(onMiss(id), a => driver.set(id, a)),
|
|
226
|
-
onSome: Effect.succeed,
|
|
227
|
-
}),
|
|
228
|
-
)
|
|
229
|
-
|
|
230
|
-
const put = (_: A) => driver.set(identify(_), _)
|
|
231
|
-
|
|
232
|
-
const update = <R, E>(id: string, f: (_: A) => Effect.Effect<A, E, R>) =>
|
|
233
|
-
Effect.flatMap(get(id), a =>
|
|
234
|
-
Effect.tap(f(a), next => driver.set(id, next)),
|
|
235
|
-
)
|
|
236
|
-
|
|
237
|
-
return {
|
|
238
|
-
...driver,
|
|
239
|
-
get,
|
|
240
|
-
put,
|
|
241
|
-
update,
|
|
242
|
-
} as const
|
|
243
|
-
}).pipe(
|
|
244
|
-
Effect.annotateLogs({
|
|
245
|
-
package: "dfx",
|
|
246
|
-
service: "Cache",
|
|
247
|
-
}),
|
|
248
|
-
)
|
|
249
|
-
|
|
250
|
-
export const CacheErrorTypeId = Symbol.for("dfx/Cache/CacheError")
|
|
251
|
-
|
|
252
|
-
export class CacheMissError extends Data.Error<{
|
|
253
|
-
cacheName: string
|
|
254
|
-
id: string
|
|
255
|
-
}> {
|
|
256
|
-
readonly _tag = "CacheMissError"
|
|
257
|
-
|
|
258
|
-
get message() {
|
|
259
|
-
return `Cache miss for "${this.cacheName}" with id: ${this.id}`
|
|
260
|
-
}
|
|
261
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import * as Discord from "./types.ts"
|
|
2
|
-
import * as Config from "effect/Config"
|
|
3
|
-
import * as Duration from "effect/Duration"
|
|
4
|
-
import * as Effect from "effect/Effect"
|
|
5
|
-
import * as Layer from "effect/Layer"
|
|
6
|
-
import type * as Redacted from "effect/Redacted"
|
|
7
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
8
|
-
|
|
9
|
-
const VERSION = 10
|
|
10
|
-
|
|
11
|
-
export interface DiscordConfigService {
|
|
12
|
-
readonly token: Redacted.Redacted
|
|
13
|
-
readonly rest: {
|
|
14
|
-
readonly baseUrl: string
|
|
15
|
-
readonly globalRateLimit: {
|
|
16
|
-
readonly limit: number
|
|
17
|
-
readonly window: Duration.Input
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
readonly gateway: {
|
|
21
|
-
readonly intents: number
|
|
22
|
-
readonly presence?: Discord.GatewayPresenceUpdateData
|
|
23
|
-
readonly shardCount?: number
|
|
24
|
-
|
|
25
|
-
readonly identifyRateLimit: readonly [window: number, limit: number]
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
export class DiscordConfig extends ServiceMap.Service<
|
|
29
|
-
DiscordConfig,
|
|
30
|
-
DiscordConfigService
|
|
31
|
-
>()("dfx/DiscordConfig") {}
|
|
32
|
-
|
|
33
|
-
export interface MakeOpts {
|
|
34
|
-
readonly token: Redacted.Redacted
|
|
35
|
-
readonly rest?: Partial<DiscordConfigService["rest"]>
|
|
36
|
-
readonly gateway?: Partial<DiscordConfigService["gateway"]>
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export const make = ({
|
|
40
|
-
gateway,
|
|
41
|
-
rest,
|
|
42
|
-
token,
|
|
43
|
-
}: MakeOpts): DiscordConfigService => ({
|
|
44
|
-
token,
|
|
45
|
-
rest: {
|
|
46
|
-
baseUrl: `https://discord.com/api/v${VERSION}`,
|
|
47
|
-
...rest,
|
|
48
|
-
globalRateLimit: {
|
|
49
|
-
limit: 50,
|
|
50
|
-
window: Duration.seconds(1),
|
|
51
|
-
...rest?.globalRateLimit,
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
gateway: {
|
|
55
|
-
intents: Discord.GatewayIntentBits.Guilds,
|
|
56
|
-
identifyRateLimit: [5000, 1],
|
|
57
|
-
...gateway,
|
|
58
|
-
},
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
export const layer = (opts: MakeOpts): Layer.Layer<DiscordConfig> =>
|
|
62
|
-
Layer.succeed(DiscordConfig, make(opts))
|
|
63
|
-
|
|
64
|
-
export const layerConfig = (
|
|
65
|
-
_: Config.Wrap<MakeOpts>,
|
|
66
|
-
): Layer.Layer<DiscordConfig, Config.ConfigError> =>
|
|
67
|
-
Layer.effect(DiscordConfig, Effect.map(Config.unwrap(_).asEffect(), make))
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import * as Effect from "effect/Effect"
|
|
2
|
-
import * as Layer from "effect/Layer"
|
|
3
|
-
import * as Ref from "effect/Ref"
|
|
4
|
-
import type * as Discord from "../types.ts"
|
|
5
|
-
import * as Schedule from "effect/Schedule"
|
|
6
|
-
import * as Cause from "effect/Cause"
|
|
7
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
8
|
-
import * as Queue from "effect/Queue"
|
|
9
|
-
import * as Socket from "effect/unstable/socket/Socket"
|
|
10
|
-
import type * as Scope from "effect/Scope"
|
|
11
|
-
import { CurrentLoggers } from "effect/Logger"
|
|
12
|
-
import * as LogLevel from "effect/LogLevel"
|
|
13
|
-
import { MinimumLogLevel } from "effect/References"
|
|
14
|
-
|
|
15
|
-
export type Message = Discord.GatewayReceivePayload
|
|
16
|
-
export type MessageSend = Discord.GatewaySendPayload | Reconnect
|
|
17
|
-
|
|
18
|
-
export const Reconnect = Symbol.for("dfx/DiscordGateway/WS/Reconnect")
|
|
19
|
-
export type Reconnect = typeof Reconnect
|
|
20
|
-
|
|
21
|
-
export interface OpenOpts {
|
|
22
|
-
url?: string
|
|
23
|
-
version?: number
|
|
24
|
-
encoding?: DiscordWSCodec
|
|
25
|
-
onConnecting: Effect.Effect<void>
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface DiscordWSCodecService {
|
|
29
|
-
type: "json" | "etf"
|
|
30
|
-
encode: (p: Discord.GatewaySendPayload) => Uint8Array | string
|
|
31
|
-
decode: (p: Uint8Array | string) => Discord.GatewayReceivePayload
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const decoder = new TextDecoder()
|
|
35
|
-
|
|
36
|
-
export class DiscordWSCodec extends ServiceMap.Service<
|
|
37
|
-
DiscordWSCodec,
|
|
38
|
-
DiscordWSCodecService
|
|
39
|
-
>()("dfx/DiscordGateway/DiscordWS/Codec") {}
|
|
40
|
-
|
|
41
|
-
export const JsonDiscordWSCodecLive = Layer.succeed(DiscordWSCodec, {
|
|
42
|
-
type: "json",
|
|
43
|
-
encode: p => JSON.stringify(p),
|
|
44
|
-
decode: p => JSON.parse(typeof p === "string" ? p : decoder.decode(p)),
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
const make = Effect.gen(function* () {
|
|
48
|
-
const encoding = yield* DiscordWSCodec
|
|
49
|
-
|
|
50
|
-
const connect = Effect.fnUntraced(
|
|
51
|
-
function* ({
|
|
52
|
-
onConnecting,
|
|
53
|
-
url = "wss://gateway.discord.gg/",
|
|
54
|
-
version = 10,
|
|
55
|
-
}: OpenOpts) {
|
|
56
|
-
const urlRef = yield* Ref.make(
|
|
57
|
-
`${url}?v=${version}&encoding=${encoding.type}`,
|
|
58
|
-
)
|
|
59
|
-
const setUrl = (nextUrl: string) =>
|
|
60
|
-
Ref.set(urlRef, `${nextUrl}?v=${version}&encoding=${encoding.type}`)
|
|
61
|
-
const messages = yield* Queue.make<Message>()
|
|
62
|
-
const socket = yield* Socket.makeWebSocket(Ref.get(urlRef), {
|
|
63
|
-
closeCodeIsError: _ => true,
|
|
64
|
-
openTimeout: 5000,
|
|
65
|
-
})
|
|
66
|
-
const writeRaw = yield* socket.writer
|
|
67
|
-
const logWriteError = (cause: Cause.Cause<Socket.SocketError>) =>
|
|
68
|
-
Effect.annotateLogs(Effect.logDebug(cause), {
|
|
69
|
-
module: "DiscordGateway/DiscordWS",
|
|
70
|
-
channel: "outbound",
|
|
71
|
-
})
|
|
72
|
-
const write = (message: MessageSend): Effect.Effect<void> => {
|
|
73
|
-
if (message === Reconnect) {
|
|
74
|
-
return Effect.catchCause(
|
|
75
|
-
writeRaw(new Socket.CloseEvent(3000, "reconnecting")),
|
|
76
|
-
logWriteError,
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
return Effect.catchCause(
|
|
80
|
-
writeRaw(encoding.encode(message)),
|
|
81
|
-
logWriteError,
|
|
82
|
-
)
|
|
83
|
-
}
|
|
84
|
-
const traceEnabled = LogLevel.isLessThanOrEqualTo(
|
|
85
|
-
yield* MinimumLogLevel,
|
|
86
|
-
"Trace",
|
|
87
|
-
)
|
|
88
|
-
const loggers = yield* CurrentLoggers
|
|
89
|
-
yield* onConnecting.pipe(
|
|
90
|
-
Effect.andThen(
|
|
91
|
-
Effect.withFiber<void, Socket.SocketError>(fiber =>
|
|
92
|
-
socket.runRaw(_ => {
|
|
93
|
-
const message = encoding.decode(_)
|
|
94
|
-
Queue.offerUnsafe(messages, message)
|
|
95
|
-
if (!traceEnabled) return
|
|
96
|
-
loggers.forEach(logger => {
|
|
97
|
-
logger.log({
|
|
98
|
-
message,
|
|
99
|
-
cause: Cause.empty,
|
|
100
|
-
fiber,
|
|
101
|
-
logLevel: "Trace",
|
|
102
|
-
date: new Date(),
|
|
103
|
-
})
|
|
104
|
-
})
|
|
105
|
-
}),
|
|
106
|
-
),
|
|
107
|
-
),
|
|
108
|
-
Effect.retry({
|
|
109
|
-
while: e =>
|
|
110
|
-
e.reason._tag === "SocketCloseError" && e.reason.code === 3000,
|
|
111
|
-
}),
|
|
112
|
-
Effect.catchCause(cause =>
|
|
113
|
-
Effect.logDebug("Got socket error, reconnecting", cause),
|
|
114
|
-
),
|
|
115
|
-
Effect.repeat(
|
|
116
|
-
Schedule.exponential(500).pipe(
|
|
117
|
-
Schedule.either(Schedule.spaced(10000)),
|
|
118
|
-
),
|
|
119
|
-
),
|
|
120
|
-
Effect.annotateLogs("channel", "inbound"),
|
|
121
|
-
Effect.forkScoped,
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
return {
|
|
125
|
-
take: Queue.take(messages),
|
|
126
|
-
setUrl,
|
|
127
|
-
write,
|
|
128
|
-
} as const
|
|
129
|
-
},
|
|
130
|
-
Effect.annotateLogs({
|
|
131
|
-
module: "DiscordGateway/DiscordWS",
|
|
132
|
-
}),
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
return { connect } as const
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
export class DiscordWS extends ServiceMap.Service<
|
|
139
|
-
DiscordWS,
|
|
140
|
-
{
|
|
141
|
-
readonly connect: (args_0: OpenOpts) => Effect.Effect<
|
|
142
|
-
{
|
|
143
|
-
readonly take: Effect.Effect<
|
|
144
|
-
Discord.GatewayReceivePayload,
|
|
145
|
-
never,
|
|
146
|
-
never
|
|
147
|
-
>
|
|
148
|
-
readonly setUrl: (url: string) => Effect.Effect<void, never, never>
|
|
149
|
-
readonly write: (message: MessageSend) => Effect.Effect<void>
|
|
150
|
-
},
|
|
151
|
-
never,
|
|
152
|
-
Socket.WebSocketConstructor | Scope.Scope
|
|
153
|
-
>
|
|
154
|
-
}
|
|
155
|
-
>()("dfx/DiscordGateway/DiscordWS") {}
|
|
156
|
-
|
|
157
|
-
export const DiscordWSLive = Layer.effect(DiscordWS, make)
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import * as Effect from "effect/Effect"
|
|
2
|
-
import * as PubSub from "effect/PubSub"
|
|
3
|
-
import * as Layer from "effect/Layer"
|
|
4
|
-
import * as Stream from "effect/Stream"
|
|
5
|
-
import type * as Discord from "../types.ts"
|
|
6
|
-
import * as EffectUtils from "../utils/Effect.ts"
|
|
7
|
-
import * as Queue from "effect/Queue"
|
|
8
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
9
|
-
|
|
10
|
-
const fromDispatchFactory =
|
|
11
|
-
<R, E>(source: Stream.Stream<Discord.GatewayReceivePayload, E, R>) =>
|
|
12
|
-
<K extends `${Discord.GatewayDispatchEvents}`>(
|
|
13
|
-
event: K,
|
|
14
|
-
): Stream.Stream<
|
|
15
|
-
Extract<Discord.DistributedGatewayDispatchPayload, { readonly t: K }>["d"],
|
|
16
|
-
E,
|
|
17
|
-
R
|
|
18
|
-
> =>
|
|
19
|
-
Stream.map(
|
|
20
|
-
Stream.filter(source, p => p.t === event),
|
|
21
|
-
p => p.d,
|
|
22
|
-
) as any
|
|
23
|
-
|
|
24
|
-
const handleDispatchFactory =
|
|
25
|
-
(hub: PubSub.PubSub<Discord.GatewayReceivePayload>) =>
|
|
26
|
-
<K extends `${Discord.GatewayDispatchEvents}`, R, E, A>(
|
|
27
|
-
event: K,
|
|
28
|
-
handle: (
|
|
29
|
-
event: Extract<Discord.GatewayDispatchPayload, { readonly t: K }>["d"],
|
|
30
|
-
) => Effect.Effect<A, E, R>,
|
|
31
|
-
): Effect.Effect<never, E, R> =>
|
|
32
|
-
EffectUtils.subscribeForEachPar(hub, _ => {
|
|
33
|
-
if (_.t === event) {
|
|
34
|
-
return handle(_.d as any)
|
|
35
|
-
}
|
|
36
|
-
return Effect.void as any
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
export const make = Effect.gen(function* () {
|
|
40
|
-
const hub = yield* Effect.acquireRelease(
|
|
41
|
-
PubSub.unbounded<Discord.GatewayReceivePayload>(),
|
|
42
|
-
PubSub.shutdown,
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
const sendMailbox = yield* Effect.acquireRelease(
|
|
46
|
-
Queue.make<Discord.GatewaySendPayload>(),
|
|
47
|
-
Queue.shutdown,
|
|
48
|
-
)
|
|
49
|
-
const send = (payload: Discord.GatewaySendPayload) =>
|
|
50
|
-
Queue.offer(sendMailbox, payload)
|
|
51
|
-
|
|
52
|
-
const dispatch = Stream.fromPubSub(hub)
|
|
53
|
-
const fromDispatch = fromDispatchFactory(dispatch)
|
|
54
|
-
const handleDispatch = handleDispatchFactory(hub)
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
hub,
|
|
58
|
-
sendMailbox,
|
|
59
|
-
dispatch,
|
|
60
|
-
fromDispatch,
|
|
61
|
-
handleDispatch,
|
|
62
|
-
send,
|
|
63
|
-
} as const
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
export class Messaging extends ServiceMap.Service<Messaging>()(
|
|
67
|
-
"dfx/DiscordGateway/Messaging",
|
|
68
|
-
{ make },
|
|
69
|
-
) {}
|
|
70
|
-
export type Messsaging = Messaging
|
|
71
|
-
export const MesssagingLive = Layer.effect(Messaging, make)
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import * as Effect from "effect/Effect"
|
|
2
|
-
import * as Option from "effect/Option"
|
|
3
|
-
import * as Layer from "effect/Layer"
|
|
4
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
5
|
-
import * as KeyValueStore from "effect/unstable/persistence/KeyValueStore"
|
|
6
|
-
import { flow, pipe } from "effect/Function"
|
|
7
|
-
|
|
8
|
-
export interface ShardState {
|
|
9
|
-
readonly resumeUrl: string
|
|
10
|
-
readonly sequence: number | null
|
|
11
|
-
readonly sessionId: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface StateStore {
|
|
15
|
-
readonly get: Effect.Effect<Option.Option<ShardState>>
|
|
16
|
-
readonly set: (state: ShardState) => Effect.Effect<void>
|
|
17
|
-
readonly clear: Effect.Effect<void>
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export class ShardStateStore extends ServiceMap.Service<
|
|
21
|
-
ShardStateStore,
|
|
22
|
-
{ readonly forShard: (id: [id: number, count: number]) => StateStore }
|
|
23
|
-
>()("dfx/Shard/StateStore") {
|
|
24
|
-
static MemoryLive: Layer.Layer<ShardStateStore> = Layer.sync(
|
|
25
|
-
ShardStateStore,
|
|
26
|
-
() => {
|
|
27
|
-
const store = new Map<string, ShardState>()
|
|
28
|
-
|
|
29
|
-
return ShardStateStore.of({
|
|
30
|
-
forShard: ([id, count]) => {
|
|
31
|
-
const key = `${id}-${count}`
|
|
32
|
-
return {
|
|
33
|
-
get: Effect.sync(() => Option.fromUndefinedOr(store.get(key))),
|
|
34
|
-
set(state) {
|
|
35
|
-
return Effect.sync(() => {
|
|
36
|
-
store.set(key, state)
|
|
37
|
-
})
|
|
38
|
-
},
|
|
39
|
-
clear: Effect.sync(() => {
|
|
40
|
-
store.delete(key)
|
|
41
|
-
}),
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
})
|
|
45
|
-
},
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
static KVSLive: Layer.Layer<
|
|
49
|
-
ShardStateStore,
|
|
50
|
-
never,
|
|
51
|
-
KeyValueStore.KeyValueStore
|
|
52
|
-
> = Layer.effect(
|
|
53
|
-
ShardStateStore,
|
|
54
|
-
Effect.gen(function* () {
|
|
55
|
-
const store = yield* KeyValueStore.KeyValueStore
|
|
56
|
-
return ShardStateStore.of({
|
|
57
|
-
forShard([id, count]) {
|
|
58
|
-
const key = `dfx-shard-state-${id}-${count}`
|
|
59
|
-
return {
|
|
60
|
-
get: pipe(
|
|
61
|
-
store.get(key),
|
|
62
|
-
Effect.orDie,
|
|
63
|
-
Effect.map(flow(Option.fromUndefinedOr, Option.map(JSON.parse))),
|
|
64
|
-
),
|
|
65
|
-
set: state => Effect.orDie(store.set(key, JSON.stringify(state))),
|
|
66
|
-
clear: Effect.orDie(store.remove(key)),
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
})
|
|
70
|
-
}),
|
|
71
|
-
)
|
|
72
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import * as Option from "effect/Option"
|
|
2
|
-
import * as Effect from "effect/Effect"
|
|
3
|
-
import * as Ref from "effect/Ref"
|
|
4
|
-
import * as DiscordWS from "../DiscordWS.ts"
|
|
5
|
-
import * as SendEvents from "./sendEvents.ts"
|
|
6
|
-
import type * as Discord from "../../types.ts"
|
|
7
|
-
import * as EffectU from "../../utils/Effect.ts"
|
|
8
|
-
import type { ShardState } from "./StateStore.ts"
|
|
9
|
-
import * as Queue from "effect/Queue"
|
|
10
|
-
|
|
11
|
-
const payload = (state: Effect.Effect<Option.Option<ShardState>>) =>
|
|
12
|
-
Effect.map(state, shardState =>
|
|
13
|
-
SendEvents.heartbeat(
|
|
14
|
-
Option.getOrNull(Option.map(shardState, s => s.sequence)),
|
|
15
|
-
),
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
const payloadOrReconnect = (
|
|
19
|
-
ref: Ref.Ref<boolean>,
|
|
20
|
-
state: Effect.Effect<Option.Option<ShardState>>,
|
|
21
|
-
) =>
|
|
22
|
-
Effect.flatMap(
|
|
23
|
-
Ref.get(ref),
|
|
24
|
-
(acked): Effect.Effect<DiscordWS.MessageSend> =>
|
|
25
|
-
acked ? payload(state) : Effect.succeed(DiscordWS.Reconnect),
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
export const send = (
|
|
29
|
-
hellos: Queue.Dequeue<Discord.GatewayHelloData>,
|
|
30
|
-
acks: Queue.Dequeue<void>,
|
|
31
|
-
state: Effect.Effect<Option.Option<ShardState>>,
|
|
32
|
-
sendMessage: (p: DiscordWS.MessageSend) => Effect.Effect<void>,
|
|
33
|
-
) =>
|
|
34
|
-
Effect.flatMap(Ref.make(true), ackedRef => {
|
|
35
|
-
const sendPayload = payloadOrReconnect(ackedRef, state).pipe(
|
|
36
|
-
Effect.tap(Ref.set(ackedRef, false)),
|
|
37
|
-
Effect.flatMap(sendMessage),
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
const heartbeats = EffectU.foreverSwitch(
|
|
41
|
-
Effect.tap(Queue.take(hellos), Ref.set(ackedRef, true)),
|
|
42
|
-
Effect.fnUntraced(function* (p) {
|
|
43
|
-
yield* Effect.sleep(p.heartbeat_interval * Math.random())
|
|
44
|
-
while (true) {
|
|
45
|
-
yield* sendPayload
|
|
46
|
-
yield* Effect.sleep(p.heartbeat_interval)
|
|
47
|
-
}
|
|
48
|
-
}),
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
const run = Queue.take(acks).pipe(
|
|
52
|
-
Effect.tap(Ref.set(ackedRef, true)),
|
|
53
|
-
Effect.forever,
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
return Effect.all([run, heartbeats], {
|
|
57
|
-
concurrency: "unbounded",
|
|
58
|
-
discard: true,
|
|
59
|
-
})
|
|
60
|
-
})
|