diff --git a/src/DiscordGateway/Shard/StateStore.ts b/src/DiscordGateway/Shard/StateStore.ts index 6a678a8..ed6e177 100644 --- a/src/DiscordGateway/Shard/StateStore.ts +++ b/src/DiscordGateway/Shard/StateStore.ts @@ -2,6 +2,7 @@ import * as Effect from "effect/Effect" import * as Option from "effect/Option" import * as Context from "effect/Context" import * as Layer from "effect/Layer" +import * as KVS from "@effect/platform/KeyValueStore" export interface ShardState { readonly resumeUrl: string @@ -9,38 +10,58 @@ export interface ShardState { readonly sessionId: string } -export interface ShardStateStore { - readonly _: unique symbol -} - export interface StateStore { readonly get: Effect.Effect> readonly set: (state: ShardState) => Effect.Effect readonly clear: Effect.Effect } -export const ShardStateStore = Context.GenericTag< +export class ShardStateStore extends Context.Tag("dfx/Shard/StateStore")< ShardStateStore, { readonly forShard: (id: [id: number, count: number]) => StateStore } ->("dfx/Shard/StateStore") - -export const MemoryShardStateStoreLive = Layer.sync(ShardStateStore, () => { - const store = new Map() +>() { + static MemoryLive: Layer.Layer = Layer.sync( + ShardStateStore, + () => { + const store = new Map() - return ShardStateStore.of({ - forShard: ([id, count]) => { - const key = `${id}-${count}` - return { - get: Effect.sync(() => Option.fromNullable(store.get(key))), - set(state) { - return Effect.sync(() => { - store.set(key, state) - }) + return ShardStateStore.of({ + forShard: ([id, count]) => { + const key = `${id}-${count}` + return { + get: Effect.sync(() => Option.fromNullable(store.get(key))), + set(state) { + return Effect.sync(() => { + store.set(key, state) + }) + }, + clear: Effect.sync(() => { + store.delete(key) + }), + } }, - clear: Effect.sync(() => { - store.delete(key) - }), - } + }) }, - }) -}) + ) + + static KVSLive: Layer.Layer = + Layer.effect( + ShardStateStore, + Effect.gen(function* (_) { + const store = yield* KVS.KeyValueStore + return ShardStateStore.of({ + forShard([id, count]) { + const key = `dfx-shard-state-${id}-${count}` + return { + get: Effect.map( + Effect.orDie(store.get(key)), + Option.map(JSON.parse), + ), + set: state => Effect.orDie(store.set(key, JSON.stringify(state))), + clear: Effect.orDie(store.remove(key)), + } + }, + }) + }), + ) +} diff --git a/src/gateway.ts b/src/gateway.ts index a913c36..031998e 100644 --- a/src/gateway.ts +++ b/src/gateway.ts @@ -3,7 +3,7 @@ import { DiscordGatewayLive } from "dfx/DiscordGateway" import * as DiscordWS from "dfx/DiscordGateway/DiscordWS" import { JsonDiscordWSCodecLive } from "dfx/DiscordGateway/DiscordWS" import * as Shard from "dfx/DiscordGateway/Shard" -import { MemoryShardStateStoreLive } from "dfx/DiscordGateway/Shard/StateStore" +import { ShardStateStore } from "dfx/DiscordGateway/Shard/StateStore" import * as SendEvent from "dfx/DiscordGateway/Shard/sendEvents" import * as ShardStore from "dfx/DiscordGateway/ShardStore" import { MemoryShardStoreLive } from "dfx/DiscordGateway/ShardStore" @@ -32,7 +32,7 @@ export const DiscordLive = Layer.mergeAll( Layer.provide(JsonDiscordWSCodecLive), Layer.provide(MemoryRateLimitStoreLive), Layer.provide(MemoryShardStoreLive), - Layer.provide(MemoryShardStateStoreLive), + Layer.provide(ShardStateStore.MemoryLive), ) export const DiscordIxLive = InteractionsRegistryLive.pipe(