1import { assert, describe, it } from "@effect/vitest"
2import { ConfigProvider, Effect, Option } from "effect"
3import { RunnerAddress, ShardingConfig } from "effect/cluster"
4
5describe("ShardingConfig", () => {
6 it.effect("bounds runner residency and storage reads by default", () =>
7 Effect.gen(function*() {
8 assert.strictEqual(ShardingConfig.defaults.maxResidentEntities, 10_000)
9 assert.strictEqual(ShardingConfig.defaults.unprocessedMessageBatchSize, 1024)
10
11 const defaults = yield* ShardingConfig.config.parse(ConfigProvider.fromUnknown({}))
12 assert.strictEqual(defaults.maxResidentEntities, 10_000)
13 assert.strictEqual(defaults.unprocessedMessageBatchSize, 1024)
14
15 // environment values are integers only
16 const fromEnv = yield* ShardingConfig.config.parse(
17 ConfigProvider.fromUnknown({ maxResidentEntities: "500", unprocessedMessageBatchSize: "128" })
18 )
19 assert.strictEqual(fromEnv.maxResidentEntities, 500)
20 assert.strictEqual(fromEnv.unprocessedMessageBatchSize, 128)
21
22 const invalid = yield* ShardingConfig.config.parse(
23 ConfigProvider.fromUnknown({ maxResidentEntities: "unbounded" })
24 ).pipe(Effect.flip)
25 assert.strictEqual(invalid._tag, "ConfigError")
26
27 // "unbounded" is only available programmatically
28 const layer = ShardingConfig.layer({ maxResidentEntities: "unbounded" })
29 const config = yield* Effect.provide(ShardingConfig.ShardingConfig, layer)
30 assert.strictEqual(config.maxResidentEntities, "unbounded")
31 }))
32
33 it.effect("omits the optional listen address when its host is absent", () =>
34 Effect.gen(function*() {
35 const defaults = yield* ShardingConfig.config.parse(ConfigProvider.fromUnknown({}))
36 assert.ok(Option.isNone(defaults.runnerListenAddress))
37
38 const withHost = yield* ShardingConfig.config.parse(
39 ConfigProvider.fromUnknown({ listenHost: "0.0.0.0" })
40 )
41 assert.deepStrictEqual(
42 Option.getOrThrow(withHost.runnerListenAddress),
43 RunnerAddress.make("0.0.0.0", 34431)
44 )
45
46 const missingHost = yield* ShardingConfig.config.parse(
47 ConfigProvider.fromUnknown({ listenPort: "8080" })
48 )
49 assert.deepStrictEqual(missingHost.runnerListenAddress, Option.none())
50
51 const invalidPort = yield* ShardingConfig.config.parse(
52 ConfigProvider.fromUnknown({ listenHost: "0.0.0.0", listenPort: "invalid" })
53 ).pipe(Effect.flip)
54 assert.strictEqual(
55 invalidPort.cause.message,
56 `Expected a string representing a finite number
57 at ["listenPort"]`
58 )
59 }))
60
61 it.effect("rejects non-positive residency and batch limits", () =>
62 Effect.gen(function*() {
63 for (
64 const values of [
65 { maxResidentEntities: "0" },
66 { maxResidentEntities: "-1" },
67 { unprocessedMessageBatchSize: "0" },
68 { unprocessedMessageBatchSize: "-1" }
69 ]
70 ) {
71 const error = yield* ShardingConfig.config.parse(ConfigProvider.fromUnknown(values)).pipe(Effect.flip)
72 assert.strictEqual(error._tag, "ConfigError")
73 }
74 }))
75})