dfx 0.127.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cache/memory.d.ts +1 -1
- package/Cache/memory.d.ts.map +1 -1
- package/Cache/memory.js +4 -4
- package/Cache/memory.js.map +1 -1
- package/Cache/memoryTTL.d.ts +1 -1
- package/Cache/memoryTTL.d.ts.map +1 -1
- package/Cache/memoryTTL.js +6 -6
- package/Cache/memoryTTL.js.map +1 -1
- package/Cache/prelude.d.ts +6 -6
- package/Cache/prelude.d.ts.map +1 -1
- package/Cache/prelude.js +4 -4
- package/Cache/prelude.js.map +1 -1
- package/Cache.d.ts +9 -10
- package/Cache.d.ts.map +1 -1
- package/Cache.js +20 -19
- package/Cache.js.map +1 -1
- package/DiscordConfig.d.ts +8 -8
- package/DiscordConfig.d.ts.map +1 -1
- package/DiscordConfig.js +8 -7
- package/DiscordConfig.js.map +1 -1
- package/DiscordGateway/DiscordWS.d.ts +12 -12
- package/DiscordGateway/DiscordWS.d.ts.map +1 -1
- package/DiscordGateway/DiscordWS.js +30 -17
- package/DiscordGateway/DiscordWS.js.map +1 -1
- package/DiscordGateway/Messaging.d.ts +204 -10
- package/DiscordGateway/Messaging.d.ts.map +1 -1
- package/DiscordGateway/Messaging.js +10 -7
- package/DiscordGateway/Messaging.js.map +1 -1
- package/DiscordGateway/Shard/StateStore.d.ts +4 -4
- package/DiscordGateway/Shard/StateStore.d.ts.map +1 -1
- package/DiscordGateway/Shard/StateStore.js +7 -6
- package/DiscordGateway/Shard/StateStore.js.map +1 -1
- package/DiscordGateway/Shard/heartbeats.d.ts +5 -5
- package/DiscordGateway/Shard/heartbeats.d.ts.map +1 -1
- package/DiscordGateway/Shard/heartbeats.js +15 -10
- package/DiscordGateway/Shard/heartbeats.js.map +1 -1
- package/DiscordGateway/Shard/identify.d.ts +2 -2
- package/DiscordGateway/Shard/identify.d.ts.map +1 -1
- package/DiscordGateway/Shard/identify.js +2 -2
- package/DiscordGateway/Shard/identify.js.map +1 -1
- package/DiscordGateway/Shard/sendEvents.d.ts +1 -1
- package/DiscordGateway/Shard/sendEvents.d.ts.map +1 -1
- package/DiscordGateway/Shard/sendEvents.js +1 -1
- package/DiscordGateway/Shard/sendEvents.js.map +1 -1
- package/DiscordGateway/Shard/utils.d.ts +1 -1
- package/DiscordGateway/Shard/utils.d.ts.map +1 -1
- package/DiscordGateway/Shard.d.ts +16 -15
- package/DiscordGateway/Shard.d.ts.map +1 -1
- package/DiscordGateway/Shard.js +27 -21
- package/DiscordGateway/Shard.js.map +1 -1
- package/DiscordGateway/ShardStore.d.ts +4 -3
- package/DiscordGateway/ShardStore.d.ts.map +1 -1
- package/DiscordGateway/ShardStore.js +3 -2
- package/DiscordGateway/ShardStore.js.map +1 -1
- package/DiscordGateway/Sharder.d.ts +9 -8
- package/DiscordGateway/Sharder.d.ts.map +1 -1
- package/DiscordGateway/Sharder.js +19 -17
- package/DiscordGateway/Sharder.js.map +1 -1
- package/DiscordGateway.d.ts +13 -12
- package/DiscordGateway.d.ts.map +1 -1
- package/DiscordGateway.js +4 -4
- package/DiscordGateway.js.map +1 -1
- package/DiscordREST/Generated.d.ts +402 -240
- package/DiscordREST/Generated.d.ts.map +1 -1
- package/DiscordREST/Generated.js +193 -126
- package/DiscordREST/Generated.js.map +1 -1
- package/DiscordREST/utils.d.ts +1 -1
- package/DiscordREST/utils.d.ts.map +1 -1
- package/DiscordREST/utils.js +4 -3
- package/DiscordREST/utils.js.map +1 -1
- package/DiscordREST.d.ts +10 -11
- package/DiscordREST.d.ts.map +1 -1
- package/DiscordREST.js +23 -27
- package/DiscordREST.js.map +1 -1
- package/Helpers/flags.d.ts.map +1 -1
- package/Helpers/flags.js +10 -1
- package/Helpers/flags.js.map +1 -1
- package/Helpers/intents.d.ts.map +1 -1
- package/Helpers/intents.js +2 -2
- package/Helpers/intents.js.map +1 -1
- package/Helpers/interactions.d.ts +2 -2
- package/Helpers/interactions.d.ts.map +1 -1
- package/Helpers/interactions.js +12 -12
- package/Helpers/interactions.js.map +1 -1
- package/Helpers/members.d.ts +2 -2
- package/Helpers/members.d.ts.map +1 -1
- package/Helpers/members.js +1 -1
- package/Helpers/members.js.map +1 -1
- package/Helpers/permissions.d.ts +1 -1
- package/Helpers/permissions.d.ts.map +1 -1
- package/Helpers/permissions.js +4 -4
- package/Helpers/permissions.js.map +1 -1
- package/Helpers/ui.d.ts +9 -9
- package/Helpers/ui.d.ts.map +1 -1
- package/Helpers/ui.js +15 -15
- package/Helpers/ui.js.map +1 -1
- package/Interactions/builder.d.ts +6 -6
- package/Interactions/builder.d.ts.map +1 -1
- package/Interactions/builder.js +7 -7
- package/Interactions/builder.js.map +1 -1
- package/Interactions/commandHelper.d.ts +3 -19
- package/Interactions/commandHelper.d.ts.map +1 -1
- package/Interactions/commandHelper.js +11 -7
- package/Interactions/commandHelper.js.map +1 -1
- package/Interactions/context.d.ts +30 -31
- package/Interactions/context.d.ts.map +1 -1
- package/Interactions/context.js +23 -18
- package/Interactions/context.js.map +1 -1
- package/Interactions/definitions.d.ts +7 -8
- package/Interactions/definitions.d.ts.map +1 -1
- package/Interactions/gateway.d.ts +11 -12
- package/Interactions/gateway.d.ts.map +1 -1
- package/Interactions/gateway.js +22 -20
- package/Interactions/gateway.js.map +1 -1
- package/Interactions/handlers.d.ts +3 -3
- package/Interactions/handlers.d.ts.map +1 -1
- package/Interactions/handlers.js +5 -4
- package/Interactions/handlers.js.map +1 -1
- package/Interactions/index.d.ts +5 -4
- package/Interactions/index.d.ts.map +1 -1
- package/Interactions/index.js +4 -4
- package/Interactions/index.js.map +1 -1
- package/Interactions/utils.d.ts +4 -4
- package/Interactions/utils.d.ts.map +1 -1
- package/Interactions/utils.js +1 -1
- package/Interactions/utils.js.map +1 -1
- package/Interactions/webhook.d.ts +9 -11
- package/Interactions/webhook.d.ts.map +1 -1
- package/Interactions/webhook.js +16 -16
- package/Interactions/webhook.js.map +1 -1
- package/RateLimit/memory.d.ts +1 -1
- package/RateLimit/memory.d.ts.map +1 -1
- package/RateLimit/memory.js +2 -2
- package/RateLimit/memory.js.map +1 -1
- package/RateLimit.d.ts +7 -7
- package/RateLimit.d.ts.map +1 -1
- package/RateLimit.js +7 -5
- package/RateLimit.js.map +1 -1
- package/gateway.d.ts +14 -14
- package/gateway.d.ts.map +1 -1
- package/gateway.js +10 -10
- package/gateway.js.map +1 -1
- package/index.d.ts +14 -14
- package/index.d.ts.map +1 -1
- package/index.js +12 -12
- package/index.js.map +1 -1
- package/mjs/Cache/memory.mjs +4 -4
- package/mjs/Cache/memory.mjs.map +1 -1
- package/mjs/Cache/memoryTTL.mjs +6 -6
- package/mjs/Cache/memoryTTL.mjs.map +1 -1
- package/mjs/Cache/prelude.mjs +4 -4
- package/mjs/Cache/prelude.mjs.map +1 -1
- package/mjs/Cache.mjs +20 -19
- package/mjs/Cache.mjs.map +1 -1
- package/mjs/DiscordConfig.mjs +7 -7
- package/mjs/DiscordConfig.mjs.map +1 -1
- package/mjs/DiscordGateway/DiscordWS.mjs +28 -17
- package/mjs/DiscordGateway/DiscordWS.mjs.map +1 -1
- package/mjs/DiscordGateway/Messaging.mjs +9 -7
- package/mjs/DiscordGateway/Messaging.mjs.map +1 -1
- package/mjs/DiscordGateway/Shard/StateStore.mjs +7 -6
- package/mjs/DiscordGateway/Shard/StateStore.mjs.map +1 -1
- package/mjs/DiscordGateway/Shard/heartbeats.mjs +15 -10
- package/mjs/DiscordGateway/Shard/heartbeats.mjs.map +1 -1
- package/mjs/DiscordGateway/Shard/identify.mjs +2 -2
- package/mjs/DiscordGateway/Shard/identify.mjs.map +1 -1
- package/mjs/DiscordGateway/Shard/sendEvents.mjs +1 -1
- package/mjs/DiscordGateway/Shard/sendEvents.mjs.map +1 -1
- package/mjs/DiscordGateway/Shard.mjs +26 -21
- package/mjs/DiscordGateway/Shard.mjs.map +1 -1
- package/mjs/DiscordGateway/ShardStore.mjs +2 -2
- package/mjs/DiscordGateway/ShardStore.mjs.map +1 -1
- package/mjs/DiscordGateway/Sharder.mjs +18 -17
- package/mjs/DiscordGateway/Sharder.mjs.map +1 -1
- package/mjs/DiscordGateway.mjs +4 -4
- package/mjs/DiscordGateway.mjs.map +1 -1
- package/mjs/DiscordREST/Generated.mjs +192 -125
- package/mjs/DiscordREST/Generated.mjs.map +1 -1
- package/mjs/DiscordREST/utils.mjs +4 -3
- package/mjs/DiscordREST/utils.mjs.map +1 -1
- package/mjs/DiscordREST.mjs +22 -27
- package/mjs/DiscordREST.mjs.map +1 -1
- package/mjs/Helpers/flags.mjs +10 -1
- package/mjs/Helpers/flags.mjs.map +1 -1
- package/mjs/Helpers/intents.mjs +2 -2
- package/mjs/Helpers/intents.mjs.map +1 -1
- package/mjs/Helpers/interactions.mjs +12 -12
- package/mjs/Helpers/interactions.mjs.map +1 -1
- package/mjs/Helpers/members.mjs +1 -1
- package/mjs/Helpers/members.mjs.map +1 -1
- package/mjs/Helpers/permissions.mjs +4 -4
- package/mjs/Helpers/permissions.mjs.map +1 -1
- package/mjs/Helpers/ui.mjs +15 -15
- package/mjs/Helpers/ui.mjs.map +1 -1
- package/mjs/Interactions/builder.mjs +7 -7
- package/mjs/Interactions/builder.mjs.map +1 -1
- package/mjs/Interactions/commandHelper.mjs +11 -7
- package/mjs/Interactions/commandHelper.mjs.map +1 -1
- package/mjs/Interactions/context.mjs +17 -18
- package/mjs/Interactions/context.mjs.map +1 -1
- package/mjs/Interactions/gateway.mjs +21 -20
- package/mjs/Interactions/gateway.mjs.map +1 -1
- package/mjs/Interactions/handlers.mjs +5 -4
- package/mjs/Interactions/handlers.mjs.map +1 -1
- package/mjs/Interactions/index.mjs +4 -4
- package/mjs/Interactions/index.mjs.map +1 -1
- package/mjs/Interactions/utils.mjs +1 -1
- package/mjs/Interactions/utils.mjs.map +1 -1
- package/mjs/Interactions/webhook.mjs +15 -16
- package/mjs/Interactions/webhook.mjs.map +1 -1
- package/mjs/RateLimit/memory.mjs +2 -2
- package/mjs/RateLimit/memory.mjs.map +1 -1
- package/mjs/RateLimit.mjs +5 -5
- package/mjs/RateLimit.mjs.map +1 -1
- package/mjs/gateway.mjs +14 -14
- package/mjs/gateway.mjs.map +1 -1
- package/mjs/index.mjs +14 -14
- package/mjs/index.mjs.map +1 -1
- package/mjs/types.mjs +2 -2
- package/mjs/types.mjs.map +1 -1
- package/mjs/utils/Effect.mjs +34 -8
- package/mjs/utils/Effect.mjs.map +1 -1
- package/mjs/version.mjs +1 -1
- package/mjs/version.mjs.map +1 -1
- package/mjs/webhooks.mjs +3 -3
- package/mjs/webhooks.mjs.map +1 -1
- package/package.json +4 -5
- package/src/Cache/memory.ts +5 -5
- package/src/Cache/memoryTTL.ts +7 -7
- package/src/Cache/prelude.ts +10 -8
- package/src/Cache.ts +31 -35
- package/src/DiscordConfig.ts +13 -17
- package/src/DiscordGateway/DiscordWS.ts +58 -32
- package/src/DiscordGateway/Messaging.ts +13 -15
- package/src/DiscordGateway/Shard/StateStore.ts +30 -25
- package/src/DiscordGateway/Shard/heartbeats.ts +25 -28
- package/src/DiscordGateway/Shard/identify.ts +5 -4
- package/src/DiscordGateway/Shard/sendEvents.ts +1 -1
- package/src/DiscordGateway/Shard/utils.ts +1 -1
- package/src/DiscordGateway/Shard.ts +39 -35
- package/src/DiscordGateway/ShardStore.ts +6 -7
- package/src/DiscordGateway/Sharder.ts +31 -29
- package/src/DiscordGateway.ts +15 -14
- package/src/DiscordREST/Generated.ts +683 -378
- package/src/DiscordREST/utils.ts +6 -3
- package/src/DiscordREST.ts +37 -41
- package/src/Helpers/flags.ts +10 -5
- package/src/Helpers/intents.ts +2 -2
- package/src/Helpers/interactions.ts +16 -14
- package/src/Helpers/members.ts +3 -3
- package/src/Helpers/permissions.ts +5 -5
- package/src/Helpers/ui.ts +16 -16
- package/src/Interactions/builder.ts +10 -10
- package/src/Interactions/commandHelper.ts +18 -29
- package/src/Interactions/context.ts +51 -65
- package/src/Interactions/definitions.ts +3 -3
- package/src/Interactions/gateway.ts +33 -45
- package/src/Interactions/handlers.ts +8 -5
- package/src/Interactions/index.ts +5 -5
- package/src/Interactions/utils.ts +6 -6
- package/src/Interactions/webhook.ts +31 -38
- package/src/RateLimit/memory.ts +3 -3
- package/src/RateLimit.ts +18 -15
- package/src/gateway.ts +21 -21
- package/src/index.ts +17 -17
- package/src/types.ts +18 -16
- package/src/utils/Effect.ts +38 -27
- package/src/version.ts +1 -1
- package/src/webhooks.ts +7 -7
- package/tsconfig.base.json +12 -6
- package/tsconfig.examples.json +0 -1
- package/types.d.ts +4 -3
- package/types.d.ts.map +1 -1
- package/types.js +3 -3
- package/types.js.map +1 -1
- package/utils/Effect.d.ts.map +1 -1
- package/utils/Effect.js +33 -7
- package/utils/Effect.js.map +1 -1
- package/version.d.ts +1 -1
- package/version.d.ts.map +1 -1
- package/version.js +1 -1
- package/version.js.map +1 -1
- package/webhooks.d.ts +5 -5
- package/webhooks.d.ts.map +1 -1
- package/webhooks.js +3 -3
- package/webhooks.js.map +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as Effect from "effect/Effect"
|
|
2
2
|
import * as Option from "effect/Option"
|
|
3
|
-
import * as Context from "effect/Context"
|
|
4
3
|
import * as Layer from "effect/Layer"
|
|
5
|
-
import * as
|
|
4
|
+
import * as ServiceMap from "effect/ServiceMap"
|
|
5
|
+
import * as KeyValueStore from "effect/unstable/persistence/KeyValueStore"
|
|
6
|
+
import { flow, pipe } from "effect/Function"
|
|
6
7
|
|
|
7
8
|
export interface ShardState {
|
|
8
9
|
readonly resumeUrl: string
|
|
@@ -16,10 +17,10 @@ export interface StateStore {
|
|
|
16
17
|
readonly clear: Effect.Effect<void>
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
export class ShardStateStore extends
|
|
20
|
+
export class ShardStateStore extends ServiceMap.Service<
|
|
20
21
|
ShardStateStore,
|
|
21
22
|
{ readonly forShard: (id: [id: number, count: number]) => StateStore }
|
|
22
|
-
>() {
|
|
23
|
+
>()("dfx/Shard/StateStore") {
|
|
23
24
|
static MemoryLive: Layer.Layer<ShardStateStore> = Layer.sync(
|
|
24
25
|
ShardStateStore,
|
|
25
26
|
() => {
|
|
@@ -29,7 +30,7 @@ export class ShardStateStore extends Context.Tag("dfx/Shard/StateStore")<
|
|
|
29
30
|
forShard: ([id, count]) => {
|
|
30
31
|
const key = `${id}-${count}`
|
|
31
32
|
return {
|
|
32
|
-
get: Effect.sync(() => Option.
|
|
33
|
+
get: Effect.sync(() => Option.fromUndefinedOr(store.get(key))),
|
|
33
34
|
set(state) {
|
|
34
35
|
return Effect.sync(() => {
|
|
35
36
|
store.set(key, state)
|
|
@@ -44,24 +45,28 @@ export class ShardStateStore extends Context.Tag("dfx/Shard/StateStore")<
|
|
|
44
45
|
},
|
|
45
46
|
)
|
|
46
47
|
|
|
47
|
-
static KVSLive: Layer.Layer<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
+
)
|
|
67
72
|
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import * as Duration from "effect/Duration"
|
|
2
1
|
import * as Option from "effect/Option"
|
|
3
2
|
import * as Effect from "effect/Effect"
|
|
4
3
|
import * as Ref from "effect/Ref"
|
|
5
|
-
import * as
|
|
6
|
-
import * as
|
|
7
|
-
import * as
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import type * as Mailbox from "effect/Mailbox"
|
|
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"
|
|
12
10
|
|
|
13
11
|
const payload = (state: Effect.Effect<Option.Option<ShardState>>) =>
|
|
14
|
-
Effect.map(state,
|
|
15
|
-
SendEvents.heartbeat(
|
|
12
|
+
Effect.map(state, shardState =>
|
|
13
|
+
SendEvents.heartbeat(
|
|
14
|
+
Option.getOrNull(Option.map(shardState, s => s.sequence)),
|
|
15
|
+
),
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
const payloadOrReconnect = (
|
|
@@ -26,33 +26,30 @@ const payloadOrReconnect = (
|
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
export const send = (
|
|
29
|
-
hellos:
|
|
30
|
-
acks:
|
|
29
|
+
hellos: Queue.Dequeue<Discord.GatewayHelloData>,
|
|
30
|
+
acks: Queue.Dequeue<void>,
|
|
31
31
|
state: Effect.Effect<Option.Option<ShardState>>,
|
|
32
|
-
|
|
32
|
+
sendMessage: (p: DiscordWS.MessageSend) => Effect.Effect<void>,
|
|
33
33
|
) =>
|
|
34
34
|
Effect.flatMap(Ref.make(true), ackedRef => {
|
|
35
35
|
const sendPayload = payloadOrReconnect(ackedRef, state).pipe(
|
|
36
|
-
Effect.
|
|
37
|
-
Effect.flatMap(
|
|
36
|
+
Effect.tap(Ref.set(ackedRef, false)),
|
|
37
|
+
Effect.flatMap(sendMessage),
|
|
38
38
|
)
|
|
39
39
|
|
|
40
40
|
const heartbeats = EffectU.foreverSwitch(
|
|
41
|
-
Effect.
|
|
42
|
-
p
|
|
43
|
-
Effect.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Schedule.spaced(Duration.millis(p.heartbeat_interval)),
|
|
50
|
-
),
|
|
51
|
-
),
|
|
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
|
+
}),
|
|
52
49
|
)
|
|
53
50
|
|
|
54
|
-
const run =
|
|
55
|
-
Effect.
|
|
51
|
+
const run = Queue.take(acks).pipe(
|
|
52
|
+
Effect.tap(Ref.set(ackedRef, true)),
|
|
56
53
|
Effect.forever,
|
|
57
54
|
)
|
|
58
55
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as Option from "effect/Option"
|
|
2
2
|
import * as Effect from "effect/Effect"
|
|
3
|
-
import * as SendEvents from "
|
|
4
|
-
import type * as Discord from "
|
|
5
|
-
import type { ShardState } from "
|
|
3
|
+
import * as SendEvents from "./sendEvents.ts"
|
|
4
|
+
import type * as Discord from "../../types.ts"
|
|
5
|
+
import type { ShardState } from "./StateStore.ts"
|
|
6
6
|
|
|
7
7
|
declare const process: { platform?: string | undefined } | undefined
|
|
8
8
|
|
|
@@ -44,6 +44,7 @@ export const identifyOrResume = (
|
|
|
44
44
|
state,
|
|
45
45
|
Option.match({
|
|
46
46
|
onNone: () => identify(opts),
|
|
47
|
-
onSome:
|
|
47
|
+
onSome: shardState =>
|
|
48
|
+
resume(opts.token, shardState.sessionId, shardState.sequence),
|
|
48
49
|
}),
|
|
49
50
|
)
|
|
@@ -1,27 +1,26 @@
|
|
|
1
|
-
import { DiscordConfig } from "
|
|
2
|
-
import type { MessageSend } from "
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import * as Heartbeats from "dfx/DiscordGateway/Shard/heartbeats"
|
|
12
|
-
import * as Identify from "dfx/DiscordGateway/Shard/identify"
|
|
13
|
-
import { RateLimiter, RateLimiterLive } from "dfx/RateLimit"
|
|
14
|
-
import * as Discord from "dfx/types"
|
|
15
|
-
import { GenericTag } from "effect/Context"
|
|
1
|
+
import { DiscordConfig } from "../DiscordConfig.ts"
|
|
2
|
+
import type { MessageSend } from "./DiscordWS.ts"
|
|
3
|
+
import { DiscordWS, DiscordWSLive, Reconnect } from "./DiscordWS.ts"
|
|
4
|
+
import { Messaging, MesssagingLive } from "./Messaging.ts"
|
|
5
|
+
import type { ShardState } from "./Shard/StateStore.ts"
|
|
6
|
+
import { ShardStateStore } from "./Shard/StateStore.ts"
|
|
7
|
+
import * as Heartbeats from "./Shard/heartbeats.ts"
|
|
8
|
+
import * as Identify from "./Shard/identify.ts"
|
|
9
|
+
import { RateLimiter, RateLimiterLive } from "../RateLimit.ts"
|
|
10
|
+
import * as Discord from "../types.ts"
|
|
16
11
|
import * as Duration from "effect/Duration"
|
|
17
12
|
import * as Effect from "effect/Effect"
|
|
18
13
|
import * as Layer from "effect/Layer"
|
|
19
14
|
import * as Option from "effect/Option"
|
|
20
|
-
import * as Mailbox from "effect/Mailbox"
|
|
21
15
|
import * as Redacted from "effect/Redacted"
|
|
22
16
|
import type * as Types from "effect/Types"
|
|
23
17
|
import * as FiberHandle from "effect/FiberHandle"
|
|
24
18
|
import { constant, constTrue, constVoid } from "effect/Function"
|
|
19
|
+
import * as Queue from "effect/Queue"
|
|
20
|
+
import * as ServiceMap from "effect/ServiceMap"
|
|
21
|
+
import * as PubSub from "effect/PubSub"
|
|
22
|
+
import * as LogLevel from "effect/LogLevel"
|
|
23
|
+
import { MinimumLogLevel } from "effect/References"
|
|
25
24
|
|
|
26
25
|
const enum Phase {
|
|
27
26
|
Connecting,
|
|
@@ -38,6 +37,10 @@ export const make = Effect.gen(function* () {
|
|
|
38
37
|
|
|
39
38
|
const connect = Effect.fnUntraced(
|
|
40
39
|
function* (shard: [id: number, count: number]) {
|
|
40
|
+
const traceEnabled = LogLevel.isLessThanOrEqualTo(
|
|
41
|
+
yield* MinimumLogLevel,
|
|
42
|
+
"Trace",
|
|
43
|
+
)
|
|
41
44
|
const reconnectHandle = yield* FiberHandle.make()
|
|
42
45
|
let phase = Phase.Connecting
|
|
43
46
|
const stateStore = shardState.forShard(shard)
|
|
@@ -52,6 +55,7 @@ export const make = Effect.gen(function* () {
|
|
|
52
55
|
const setPhase = (p: Phase): Effect.Effect<void> =>
|
|
53
56
|
Effect.suspend(() => {
|
|
54
57
|
phase = p
|
|
58
|
+
if (!traceEnabled) return Effect.void
|
|
55
59
|
return Effect.annotateLogs(
|
|
56
60
|
Effect.logTrace("phase transition"),
|
|
57
61
|
"phase",
|
|
@@ -65,7 +69,7 @@ export const make = Effect.gen(function* () {
|
|
|
65
69
|
return write(p)
|
|
66
70
|
})
|
|
67
71
|
|
|
68
|
-
const resume = Effect.
|
|
72
|
+
const resume = Effect.andThen(
|
|
69
73
|
FiberHandle.clear(reconnectHandle),
|
|
70
74
|
setPhase(Phase.Connected),
|
|
71
75
|
)
|
|
@@ -74,18 +78,18 @@ export const make = Effect.gen(function* () {
|
|
|
74
78
|
|
|
75
79
|
const socket = yield* dws.connect({ onConnecting })
|
|
76
80
|
const write = (p: MessageSend) =>
|
|
77
|
-
Effect.
|
|
81
|
+
Effect.andThen(
|
|
78
82
|
limiter.maybeWait("dfx.shard.send", Duration.minutes(1), 120),
|
|
79
83
|
socket.write(p),
|
|
80
84
|
)
|
|
81
85
|
|
|
82
86
|
const hellos = yield* Effect.acquireRelease(
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
Queue.make<Discord.GatewayHelloData>(),
|
|
88
|
+
Queue.shutdown,
|
|
85
89
|
)
|
|
86
90
|
const acks = yield* Effect.acquireRelease(
|
|
87
|
-
|
|
88
|
-
|
|
91
|
+
Queue.make<void>(),
|
|
92
|
+
Queue.shutdown,
|
|
89
93
|
)
|
|
90
94
|
|
|
91
95
|
// heartbeats
|
|
@@ -129,12 +133,12 @@ export const make = Effect.gen(function* () {
|
|
|
129
133
|
case Discord.GatewayOpcodes.Hello: {
|
|
130
134
|
yield* write(yield* identify)
|
|
131
135
|
yield* setPhase(Phase.Handshake)
|
|
132
|
-
|
|
136
|
+
Queue.offerUnsafe(hellos, p.d)
|
|
133
137
|
yield* FiberHandle.run(reconnectHandle, delayedReconnect)
|
|
134
138
|
return
|
|
135
139
|
}
|
|
136
140
|
case Discord.GatewayOpcodes.HeartbeatAck: {
|
|
137
|
-
|
|
141
|
+
Queue.offerUnsafe(acks, void 0)
|
|
138
142
|
return
|
|
139
143
|
}
|
|
140
144
|
case Discord.GatewayOpcodes.InvalidSession: {
|
|
@@ -149,7 +153,7 @@ export const make = Effect.gen(function* () {
|
|
|
149
153
|
if (p.t === "READY" || p.t === "RESUMED") {
|
|
150
154
|
yield* resume
|
|
151
155
|
}
|
|
152
|
-
|
|
156
|
+
PubSub.publishUnsafe(hub, p)
|
|
153
157
|
return
|
|
154
158
|
}
|
|
155
159
|
case Discord.GatewayOpcodes.Reconnect: {
|
|
@@ -161,15 +165,15 @@ export const make = Effect.gen(function* () {
|
|
|
161
165
|
|
|
162
166
|
yield* Effect.whileLoop({
|
|
163
167
|
while: constTrue,
|
|
164
|
-
body: constant(Effect.flatMap(
|
|
168
|
+
body: constant(Effect.flatMap(Queue.take(sendMailbox), write)),
|
|
165
169
|
step: constVoid,
|
|
166
|
-
}).pipe(Effect.forkScoped
|
|
170
|
+
}).pipe(Effect.forkScoped)
|
|
167
171
|
|
|
168
172
|
yield* Effect.gen(function* () {
|
|
169
173
|
while (true) {
|
|
170
174
|
yield* onPayload(yield* socket.take)
|
|
171
175
|
}
|
|
172
|
-
}).pipe(Effect.forkScoped
|
|
176
|
+
}).pipe(Effect.forkScoped)
|
|
173
177
|
|
|
174
178
|
return { id: shard, write } as const
|
|
175
179
|
},
|
|
@@ -184,12 +188,11 @@ export const make = Effect.gen(function* () {
|
|
|
184
188
|
return { connect } as const
|
|
185
189
|
})
|
|
186
190
|
|
|
187
|
-
type ShardService = Effect.
|
|
191
|
+
type ShardService = Effect.Success<typeof make>
|
|
188
192
|
|
|
189
|
-
export
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
export const Shard = GenericTag<Shard, ShardService>("dfx/DiscordGateway/Shard")
|
|
193
|
+
export class Shard extends ServiceMap.Service<Shard, ShardService>()(
|
|
194
|
+
"dfx/DiscordGateway/Shard",
|
|
195
|
+
) {}
|
|
193
196
|
export const ShardLive = Layer.effect(Shard, make).pipe(
|
|
194
197
|
Layer.provide(DiscordWSLive),
|
|
195
198
|
Layer.provide(MesssagingLive),
|
|
@@ -197,5 +200,6 @@ export const ShardLive = Layer.effect(Shard, make).pipe(
|
|
|
197
200
|
)
|
|
198
201
|
|
|
199
202
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
200
|
-
export interface RunningShard
|
|
201
|
-
|
|
203
|
+
export interface RunningShard extends Effect.Success<
|
|
204
|
+
ReturnType<ShardService["connect"]>
|
|
205
|
+
> {}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { GenericTag } from "effect/Context"
|
|
2
1
|
import * as Option from "effect/Option"
|
|
3
2
|
import * as Effect from "effect/Effect"
|
|
4
3
|
import * as Layer from "effect/Layer"
|
|
4
|
+
import * as ServiceMap from "effect/ServiceMap"
|
|
5
5
|
|
|
6
6
|
export interface ClaimIdContext {
|
|
7
7
|
sharderCount: number
|
|
@@ -13,12 +13,11 @@ export interface ShardStoreService {
|
|
|
13
13
|
allClaimed: (totalCount: number) => Effect.Effect<boolean>
|
|
14
14
|
heartbeat?: (shardId: number) => Effect.Effect<void>
|
|
15
15
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
)
|
|
16
|
+
|
|
17
|
+
export class ShardStore extends ServiceMap.Service<
|
|
18
|
+
ShardStore,
|
|
19
|
+
ShardStoreService
|
|
20
|
+
>()("dfx/DiscordGateway/ShardStore") {}
|
|
22
21
|
|
|
23
22
|
// Very basic shard id store, that does no health checks
|
|
24
23
|
const memoryStore = (): ShardStoreService => {
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { DiscordConfig } from "
|
|
2
|
-
import type { RunningShard } from "
|
|
3
|
-
import { Shard, ShardLive } from "
|
|
4
|
-
import { ShardStore } from "
|
|
5
|
-
import { DiscordREST, DiscordRESTLive } from "
|
|
6
|
-
import { RateLimiter, RateLimiterLive } from "
|
|
7
|
-
import type * as Discord from "
|
|
8
|
-
import { GenericTag } from "effect/Context"
|
|
1
|
+
import { DiscordConfig } from "../DiscordConfig.ts"
|
|
2
|
+
import type { RunningShard } from "./Shard.ts"
|
|
3
|
+
import { Shard, ShardLive } from "./Shard.ts"
|
|
4
|
+
import { ShardStore } from "./ShardStore.ts"
|
|
5
|
+
import { DiscordREST, DiscordRESTLive } from "../DiscordREST.ts"
|
|
6
|
+
import { RateLimiter, RateLimiterLive } from "../RateLimit.ts"
|
|
7
|
+
import type * as Discord from "../types.ts"
|
|
9
8
|
import * as Duration from "effect/Duration"
|
|
10
9
|
import * as Effect from "effect/Effect"
|
|
11
10
|
import { pipe } from "effect/Function"
|
|
@@ -13,23 +12,25 @@ import * as Layer from "effect/Layer"
|
|
|
13
12
|
import type * as Option from "effect/Option"
|
|
14
13
|
import * as Ref from "effect/Ref"
|
|
15
14
|
import * as Schedule from "effect/Schedule"
|
|
15
|
+
import * as ServiceMap from "effect/ServiceMap"
|
|
16
16
|
|
|
17
|
-
const claimRepeatPolicy = Schedule.
|
|
18
|
-
Schedule.
|
|
17
|
+
const claimRepeatPolicy = Schedule.identity<Option.Option<number>>().pipe(
|
|
18
|
+
Schedule.either(Schedule.spaced("3 minutes")),
|
|
19
|
+
Schedule.while(_ => Effect.succeed(_.input._tag === "None")),
|
|
19
20
|
Schedule.passthrough,
|
|
20
21
|
) as Schedule.Schedule<Option.Some<number>, Option.Option<number>>
|
|
21
22
|
|
|
22
23
|
const make = Effect.gen(function* () {
|
|
23
24
|
const store = yield* ShardStore
|
|
24
25
|
const rest = yield* DiscordREST
|
|
25
|
-
const { gateway:
|
|
26
|
+
const { gateway: gatewayConfig } = yield* DiscordConfig
|
|
26
27
|
const limiter = yield* RateLimiter
|
|
27
28
|
const shard = yield* Shard
|
|
28
29
|
const currentShards = new Set<RunningShard>()
|
|
29
30
|
|
|
30
31
|
const gateway = yield* rest.getBotGateway().pipe(
|
|
31
|
-
Effect.
|
|
32
|
-
Effect.succeed<Discord.
|
|
32
|
+
Effect.catch(() =>
|
|
33
|
+
Effect.succeed<Discord.APIGatewayBotInfo>({
|
|
33
34
|
url: "wss://gateway.discord.gg/",
|
|
34
35
|
shards: 1,
|
|
35
36
|
session_start_limit: {
|
|
@@ -42,7 +43,7 @@ const make = Effect.gen(function* () {
|
|
|
42
43
|
),
|
|
43
44
|
)
|
|
44
45
|
|
|
45
|
-
const totalCount =
|
|
46
|
+
const totalCount = gatewayConfig.shardCount ?? gateway.shards
|
|
46
47
|
const currentCount = yield* Ref.make(0)
|
|
47
48
|
const claimId = (sharderCount: number): Effect.Effect<number> =>
|
|
48
49
|
pipe(
|
|
@@ -61,21 +62,22 @@ const make = Effect.gen(function* () {
|
|
|
61
62
|
|
|
62
63
|
const spawner = pipe(
|
|
63
64
|
takeConfig,
|
|
64
|
-
Effect.map(
|
|
65
|
-
...
|
|
65
|
+
Effect.map(shardConfig => ({
|
|
66
|
+
...shardConfig,
|
|
66
67
|
url: gateway.url,
|
|
67
68
|
concurrency: gateway.session_start_limit.max_concurrency,
|
|
68
69
|
})),
|
|
69
70
|
Effect.tap(({ concurrency, id }) =>
|
|
70
71
|
limiter.maybeWait(
|
|
71
72
|
`dfx.sharder.${id % concurrency}`,
|
|
72
|
-
Duration.millis(
|
|
73
|
-
|
|
73
|
+
Duration.millis(gatewayConfig.identifyRateLimit[0]),
|
|
74
|
+
gatewayConfig.identifyRateLimit[1],
|
|
74
75
|
),
|
|
75
76
|
),
|
|
76
77
|
Effect.flatMap(c => shard.connect([c.id, c.totalCount])),
|
|
77
|
-
Effect.tap(
|
|
78
|
-
currentShards.add(
|
|
78
|
+
Effect.tap(runningShard => {
|
|
79
|
+
currentShards.add(runningShard)
|
|
80
|
+
return Effect.void
|
|
79
81
|
}),
|
|
80
82
|
Effect.forever,
|
|
81
83
|
)
|
|
@@ -86,11 +88,10 @@ const make = Effect.gen(function* () {
|
|
|
86
88
|
{ concurrency: "unbounded", discard: true },
|
|
87
89
|
).pipe(
|
|
88
90
|
Effect.scoped,
|
|
89
|
-
Effect.
|
|
91
|
+
Effect.catchCause(Effect.logError),
|
|
90
92
|
Effect.ensuring(Effect.sync(() => currentShards.clear())),
|
|
91
93
|
Effect.forever,
|
|
92
94
|
Effect.forkScoped,
|
|
93
|
-
Effect.interruptible,
|
|
94
95
|
)
|
|
95
96
|
|
|
96
97
|
return {
|
|
@@ -103,13 +104,14 @@ const make = Effect.gen(function* () {
|
|
|
103
104
|
}),
|
|
104
105
|
)
|
|
105
106
|
|
|
106
|
-
export
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
)
|
|
112
|
-
|
|
107
|
+
export class Sharder extends ServiceMap.Service<
|
|
108
|
+
Sharder,
|
|
109
|
+
{
|
|
110
|
+
readonly shards: Effect.Effect<ReadonlySet<RunningShard>, never, never>
|
|
111
|
+
}
|
|
112
|
+
>()("dfx/DiscordGateway/Sharder") {}
|
|
113
|
+
|
|
114
|
+
export const SharderLive = Layer.effect(Sharder, make).pipe(
|
|
113
115
|
Layer.provide(DiscordRESTLive),
|
|
114
116
|
Layer.provide(RateLimiterLive),
|
|
115
117
|
Layer.provide(ShardLive),
|
package/src/DiscordGateway.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import type {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import type {
|
|
11
|
-
import type
|
|
12
|
-
import type * as Discord from "dfx/types"
|
|
13
|
-
import { GenericTag } from "effect/Context"
|
|
1
|
+
import type { WebSocketConstructor } from "effect/unstable/socket/Socket"
|
|
2
|
+
import type { DiscordConfig } from "./DiscordConfig.ts"
|
|
3
|
+
import type { DiscordWSCodec } from "./DiscordGateway/DiscordWS.ts"
|
|
4
|
+
import type { Messsaging } from "./DiscordGateway/Messaging.ts"
|
|
5
|
+
import { Messaging, MesssagingLive } from "./DiscordGateway/Messaging.ts"
|
|
6
|
+
import type { RunningShard } from "./DiscordGateway/Shard.ts"
|
|
7
|
+
import type { ShardStateStore } from "./DiscordGateway/Shard/StateStore.ts"
|
|
8
|
+
import { Sharder, SharderLive } from "./DiscordGateway/Sharder.ts"
|
|
9
|
+
import type { ShardStore } from "./DiscordGateway/ShardStore.ts"
|
|
10
|
+
import type { RateLimitStore } from "./RateLimit.ts"
|
|
11
|
+
import type * as Discord from "./types.ts"
|
|
14
12
|
import * as Effect from "effect/Effect"
|
|
15
13
|
import * as Layer from "effect/Layer"
|
|
16
14
|
import type * as Stream from "effect/Stream"
|
|
15
|
+
import type { HttpClient } from "effect/unstable/http/HttpClient"
|
|
16
|
+
import * as ServiceMap from "effect/ServiceMap"
|
|
17
17
|
|
|
18
18
|
export const TypeId = Symbol.for("dfx/DiscordGateway")
|
|
19
19
|
export type TypeId = typeof TypeId
|
|
@@ -45,7 +45,8 @@ export interface DiscordGateway {
|
|
|
45
45
|
readonly shards: Effect.Effect<ReadonlySet<RunningShard>>
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
export const DiscordGateway =
|
|
48
|
+
export const DiscordGateway =
|
|
49
|
+
ServiceMap.Service<DiscordGateway>("dfx/DiscordGateway")
|
|
49
50
|
|
|
50
51
|
export const make: Effect.Effect<DiscordGateway, never, Messsaging | Sharder> =
|
|
51
52
|
Effect.gen(function* () {
|