@livestore/utils 0.3.0-dev.11 → 0.3.0-dev.13
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/.tsbuildinfo.json +1 -1
- package/dist/bun/mod.d.ts +5 -0
- package/dist/bun/mod.d.ts.map +1 -0
- package/dist/bun/mod.js +9 -0
- package/dist/bun/mod.js.map +1 -0
- package/dist/effect/Effect.d.ts +4 -2
- package/dist/effect/Effect.d.ts.map +1 -1
- package/dist/effect/Effect.js +9 -1
- package/dist/effect/Effect.js.map +1 -1
- package/dist/effect/Schema/index.d.ts +1 -0
- package/dist/effect/Schema/index.d.ts.map +1 -1
- package/dist/effect/Schema/index.js +10 -0
- package/dist/effect/Schema/index.js.map +1 -1
- package/dist/effect/WebChannel/WebChannel.d.ts +61 -0
- package/dist/effect/WebChannel/WebChannel.d.ts.map +1 -0
- package/dist/effect/WebChannel/WebChannel.js +209 -0
- package/dist/effect/WebChannel/WebChannel.js.map +1 -0
- package/dist/effect/WebChannel/broadcastChannelWithAck.d.ts +5 -6
- package/dist/effect/WebChannel/broadcastChannelWithAck.d.ts.map +1 -1
- package/dist/effect/WebChannel/broadcastChannelWithAck.js +12 -8
- package/dist/effect/WebChannel/broadcastChannelWithAck.js.map +1 -1
- package/dist/effect/WebChannel/common.d.ts +16 -1
- package/dist/effect/WebChannel/common.d.ts.map +1 -1
- package/dist/effect/WebChannel/common.js +30 -1
- package/dist/effect/WebChannel/common.js.map +1 -1
- package/dist/effect/WebChannel.d.ts +5 -12
- package/dist/effect/WebChannel.d.ts.map +1 -1
- package/dist/effect/WebChannel.js +16 -31
- package/dist/effect/WebChannel.js.map +1 -1
- package/dist/effect/index.d.ts +2 -2
- package/dist/effect/index.d.ts.map +1 -1
- package/dist/effect/index.js +2 -2
- package/dist/effect/index.js.map +1 -1
- package/dist/env.d.ts +1 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +2 -0
- package/dist/env.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunner.d.ts.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunner.js +21 -10
- package/dist/node/ChildProcessRunner/ChildProcessRunner.js.map +1 -1
- package/dist/node/mod.d.ts +0 -1
- package/dist/node/mod.d.ts.map +1 -1
- package/dist/node/mod.js +4 -6
- package/dist/node/mod.js.map +1 -1
- package/package.json +33 -25
- package/src/bun/mod.ts +12 -0
- package/src/effect/Effect.ts +14 -2
- package/src/effect/Schema/index.ts +15 -0
- package/src/effect/WebChannel/WebChannel.ts +357 -0
- package/src/effect/WebChannel/broadcastChannelWithAck.ts +86 -82
- package/src/effect/WebChannel/common.ts +56 -2
- package/src/effect/index.ts +4 -1
- package/src/env.ts +4 -0
- package/src/index.ts +4 -2
- package/src/node/ChildProcessRunner/ChildProcessRunner.ts +39 -28
- package/src/node/mod.ts +6 -6
- package/tsconfig.json +1 -1
- package/src/effect/WebChannel.ts +0 -305
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Deferred, Effect, Predicate, Queue, Schema, Stream } from 'effect'
|
|
1
|
+
import { Deferred, Exit, Predicate, Queue, Schema, Scope, Stream } from 'effect'
|
|
3
2
|
|
|
4
|
-
import
|
|
3
|
+
import * as Effect from '../Effect.js'
|
|
4
|
+
import type { InputSchema, WebChannel } from './common.js'
|
|
5
5
|
import { WebChannelSymbol } from './common.js'
|
|
6
|
+
import { listenToDebugPing, mapSchema } from './WebChannel.js'
|
|
6
7
|
|
|
7
8
|
const ConnectMessage = Schema.TaggedStruct('ConnectMessage', {
|
|
8
9
|
from: Schema.String,
|
|
@@ -31,96 +32,99 @@ const Message = Schema.Union(ConnectMessage, ConnectAckMessage, DisconnectMessag
|
|
|
31
32
|
*/
|
|
32
33
|
export const broadcastChannelWithAck = <MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>({
|
|
33
34
|
channelName,
|
|
34
|
-
|
|
35
|
-
sendSchema,
|
|
35
|
+
schema: inputSchema,
|
|
36
36
|
}: {
|
|
37
37
|
channelName: string
|
|
38
|
-
|
|
39
|
-
sendSchema: Schema.Schema<MsgSend, MsgSendEncoded>
|
|
38
|
+
schema: InputSchema<MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>
|
|
40
39
|
}): Effect.Effect<WebChannel<MsgListen, MsgSend>, never, Scope.Scope> =>
|
|
41
|
-
Effect.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
Effect.scopeWithCloseable((scope) =>
|
|
41
|
+
Effect.gen(function* () {
|
|
42
|
+
const channel = new BroadcastChannel(channelName)
|
|
43
|
+
const messageQueue = yield* Queue.unbounded<MsgSend>()
|
|
44
|
+
const connectionId = crypto.randomUUID()
|
|
45
|
+
const schema = mapSchema(inputSchema)
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
const peerIdRef = { current: undefined as undefined | string }
|
|
48
|
+
const connectedLatch = yield* Effect.makeLatch(false)
|
|
49
|
+
const supportsTransferables = false
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
const postMessage = (msg: typeof Message.Type) => channel.postMessage(Schema.encodeSync(Message)(msg))
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
Effect.gen(function* () {
|
|
54
|
-
yield* connectedLatch.await
|
|
55
|
-
|
|
56
|
-
const payload = yield* Schema.encode(sendSchema)(message)
|
|
57
|
-
postMessage(PayloadMessage.make({ from: connectionId, to: peerIdRef.current!, payload }))
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
const listen = Stream.fromEventListener<MessageEvent>(channel, 'message').pipe(
|
|
61
|
-
Stream.map(({ data }) => data),
|
|
62
|
-
Stream.map(Schema.decodeOption(Message)),
|
|
63
|
-
Stream.filterMap((_) => _),
|
|
64
|
-
Stream.mapEffect((data) =>
|
|
53
|
+
const send = (message: MsgSend) =>
|
|
65
54
|
Effect.gen(function* () {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
55
|
+
yield* connectedLatch.await
|
|
56
|
+
|
|
57
|
+
const payload = yield* Schema.encode(schema.send)(message)
|
|
58
|
+
postMessage(PayloadMessage.make({ from: connectionId, to: peerIdRef.current!, payload }))
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
const listen = Stream.fromEventListener<MessageEvent>(channel, 'message').pipe(
|
|
62
|
+
Stream.map(({ data }) => data),
|
|
63
|
+
Stream.map(Schema.decodeOption(Message)),
|
|
64
|
+
Stream.filterMap((_) => _),
|
|
65
|
+
Stream.mapEffect((data) =>
|
|
66
|
+
Effect.gen(function* () {
|
|
67
|
+
switch (data._tag) {
|
|
68
|
+
// Case: other side sends connect message (because otherside wasn't yet online when this side send their connect message)
|
|
69
|
+
case 'ConnectMessage': {
|
|
77
70
|
peerIdRef.current = data.from
|
|
71
|
+
postMessage(ConnectAckMessage.make({ from: connectionId, to: data.from }))
|
|
78
72
|
yield* connectedLatch.open
|
|
73
|
+
break
|
|
79
74
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
75
|
+
// Case: other side sends connect-ack message (because otherside was already online when this side connected)
|
|
76
|
+
case 'ConnectAckMessage': {
|
|
77
|
+
if (data.to === connectionId) {
|
|
78
|
+
peerIdRef.current = data.from
|
|
79
|
+
yield* connectedLatch.open
|
|
80
|
+
}
|
|
81
|
+
break
|
|
87
82
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
83
|
+
case 'DisconnectMessage': {
|
|
84
|
+
if (data.from === peerIdRef.current) {
|
|
85
|
+
peerIdRef.current = undefined
|
|
86
|
+
yield* connectedLatch.close
|
|
87
|
+
yield* establishConnection
|
|
88
|
+
}
|
|
89
|
+
break
|
|
90
|
+
}
|
|
91
|
+
case 'PayloadMessage': {
|
|
92
|
+
if (data.to === connectionId) {
|
|
93
|
+
return Schema.decodeEither(schema.listen)(data.payload)
|
|
94
|
+
}
|
|
95
|
+
break
|
|
93
96
|
}
|
|
94
|
-
break
|
|
95
97
|
}
|
|
96
|
-
}
|
|
98
|
+
}),
|
|
99
|
+
),
|
|
100
|
+
Stream.filter(Predicate.isNotUndefined),
|
|
101
|
+
listenToDebugPing(channelName),
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
const establishConnection = Effect.gen(function* () {
|
|
105
|
+
postMessage(ConnectMessage.make({ from: connectionId }))
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
yield* establishConnection
|
|
109
|
+
|
|
110
|
+
yield* Effect.addFinalizer(() =>
|
|
111
|
+
Effect.gen(function* () {
|
|
112
|
+
postMessage(DisconnectMessage.make({ from: connectionId }))
|
|
113
|
+
channel.close()
|
|
114
|
+
yield* Queue.shutdown(messageQueue)
|
|
97
115
|
}),
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}),
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
const closedDeferred = yield* Deferred.make<void>()
|
|
117
|
-
|
|
118
|
-
return {
|
|
119
|
-
[WebChannelSymbol]: WebChannelSymbol,
|
|
120
|
-
send,
|
|
121
|
-
listen,
|
|
122
|
-
closedDeferred,
|
|
123
|
-
schema: { listen: listenSchema, send: sendSchema },
|
|
124
|
-
supportsTransferables,
|
|
125
|
-
}
|
|
126
|
-
}).pipe(Effect.withSpan(`WebChannel:broadcastChannelWithAck(${channelName})`))
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
const closedDeferred = yield* Deferred.make<void>().pipe(Effect.acquireRelease(Deferred.done(Exit.void)))
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
[WebChannelSymbol]: WebChannelSymbol,
|
|
122
|
+
send,
|
|
123
|
+
listen,
|
|
124
|
+
closedDeferred,
|
|
125
|
+
shutdown: Scope.close(scope, Exit.void),
|
|
126
|
+
schema,
|
|
127
|
+
supportsTransferables,
|
|
128
|
+
}
|
|
129
|
+
}).pipe(Effect.withSpan(`WebChannel:broadcastChannelWithAck(${channelName})`)),
|
|
130
|
+
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Deferred, Effect, Either, ParseResult
|
|
2
|
-
import { Predicate } from 'effect'
|
|
1
|
+
import type { Deferred, Effect, Either, ParseResult } from 'effect'
|
|
2
|
+
import { Predicate, Schema, Stream } from 'effect'
|
|
3
3
|
|
|
4
4
|
export const WebChannelSymbol = Symbol('WebChannel')
|
|
5
5
|
export type WebChannelSymbol = typeof WebChannelSymbol
|
|
@@ -13,5 +13,59 @@ export interface WebChannel<MsgListen, MsgSend, E = never> {
|
|
|
13
13
|
listen: Stream.Stream<Either.Either<MsgListen, ParseResult.ParseError>, E>
|
|
14
14
|
supportsTransferables: boolean
|
|
15
15
|
closedDeferred: Deferred.Deferred<void>
|
|
16
|
+
shutdown: Effect.Effect<void>
|
|
16
17
|
schema: { listen: Schema.Schema<MsgListen, any>; send: Schema.Schema<MsgSend, any> }
|
|
18
|
+
debugInfo?: Record<string, any>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const DebugPingMessage = Schema.TaggedStruct('WebChannel.DebugPing', {
|
|
22
|
+
message: Schema.String,
|
|
23
|
+
payload: Schema.optional(Schema.String),
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
export const schemaWithDebugPing = <MsgListen, MsgSend>(
|
|
27
|
+
schema: OutputSchema<MsgListen, MsgSend, any, any>,
|
|
28
|
+
): OutputSchema<MsgListen | typeof DebugPingMessage.Type, MsgSend | typeof DebugPingMessage.Type, any, any> => ({
|
|
29
|
+
send: Schema.Union(schema.send, DebugPingMessage),
|
|
30
|
+
listen: Schema.Union(schema.listen, DebugPingMessage),
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
export type InputSchema<MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded> =
|
|
34
|
+
| Schema.Schema<MsgListen | MsgSend, MsgListenEncoded | MsgSendEncoded>
|
|
35
|
+
| OutputSchema<MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>
|
|
36
|
+
|
|
37
|
+
export type OutputSchema<MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded> = {
|
|
38
|
+
listen: Schema.Schema<MsgListen, MsgListenEncoded>
|
|
39
|
+
send: Schema.Schema<MsgSend, MsgSendEncoded>
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const mapSchema = <MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>(
|
|
43
|
+
schema: InputSchema<MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>,
|
|
44
|
+
): OutputSchema<MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded> =>
|
|
45
|
+
Predicate.hasProperty(schema, 'send') && Predicate.hasProperty(schema, 'listen')
|
|
46
|
+
? schemaWithDebugPing(schema)
|
|
47
|
+
: (schemaWithDebugPing({ send: schema, listen: schema }) as any)
|
|
48
|
+
|
|
49
|
+
export const listenToDebugPing = (channelName: string) => {
|
|
50
|
+
const threadName = (() => {
|
|
51
|
+
if (typeof globalThis !== 'undefined' && Predicate.hasProperty(globalThis, 'name') && self.name !== '') {
|
|
52
|
+
return self.name
|
|
53
|
+
} else if (typeof globalThis !== 'undefined') {
|
|
54
|
+
return 'window'
|
|
55
|
+
}
|
|
56
|
+
return 'unknown thread'
|
|
57
|
+
})()
|
|
58
|
+
|
|
59
|
+
return <MsgListen>(
|
|
60
|
+
stream: Stream.Stream<Either.Either<MsgListen, ParseResult.ParseError>, never>,
|
|
61
|
+
): Stream.Stream<Either.Either<MsgListen, ParseResult.ParseError>, never> =>
|
|
62
|
+
stream.pipe(
|
|
63
|
+
Stream.filter((msg) => {
|
|
64
|
+
if (msg._tag === 'Right' && Schema.is(DebugPingMessage)(msg.right)) {
|
|
65
|
+
console.log(`[${threadName}] WebChannel:ping [${channelName}]`, msg.right.message, msg.right.payload)
|
|
66
|
+
return false
|
|
67
|
+
}
|
|
68
|
+
return true
|
|
69
|
+
}),
|
|
70
|
+
)
|
|
17
71
|
}
|
package/src/effect/index.ts
CHANGED
|
@@ -56,6 +56,9 @@ export {
|
|
|
56
56
|
Match,
|
|
57
57
|
TestServices,
|
|
58
58
|
Mailbox,
|
|
59
|
+
ExecutionStrategy,
|
|
60
|
+
PrimaryKey,
|
|
61
|
+
Types,
|
|
59
62
|
} from 'effect'
|
|
60
63
|
|
|
61
64
|
export { dual } from 'effect/Function'
|
|
@@ -69,7 +72,7 @@ export * as Subscribable from './Subscribable.js'
|
|
|
69
72
|
|
|
70
73
|
export * as Logger from './Logger.js'
|
|
71
74
|
|
|
72
|
-
export * as WebChannel from './WebChannel.js'
|
|
75
|
+
export * as WebChannel from './WebChannel/WebChannel.js'
|
|
73
76
|
export * as WebSocket from './WebSocket.js'
|
|
74
77
|
|
|
75
78
|
export * as SchemaAST from 'effect/SchemaAST'
|
package/src/env.ts
CHANGED
|
@@ -29,3 +29,7 @@ export const isDevEnv = () => {
|
|
|
29
29
|
export const TRACE_VERBOSE = env('LS_TRACE_VERBOSE') !== undefined || env('VITE_LS_TRACE_VERBOSE') !== undefined
|
|
30
30
|
|
|
31
31
|
export const LS_DEV = env('LS_DEV') !== undefined || env('VITE_LS_DEV') !== undefined
|
|
32
|
+
|
|
33
|
+
const envTruish = (env: string | undefined) => env !== undefined && env !== 'false' && env !== '0'
|
|
34
|
+
|
|
35
|
+
export const IS_CI = envTruish(env('CI'))
|
package/src/index.ts
CHANGED
|
@@ -14,12 +14,12 @@ export * as base64 from './base64.js'
|
|
|
14
14
|
export { default as prettyBytes } from 'pretty-bytes'
|
|
15
15
|
|
|
16
16
|
import type * as otel from '@opentelemetry/api'
|
|
17
|
+
import type { Types } from 'effect'
|
|
17
18
|
|
|
18
19
|
import { isDevEnv } from './env.js'
|
|
19
20
|
import { objectToString } from './misc.js'
|
|
20
21
|
|
|
21
22
|
export type Prettify<T> = T extends infer U ? { [K in keyof U]: Prettify<U[K]> } : never
|
|
22
|
-
export type PrettifyFlat<T> = T extends infer U ? { [K in keyof U]: U[K] } : never
|
|
23
23
|
|
|
24
24
|
export type TypeEq<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false
|
|
25
25
|
|
|
@@ -30,6 +30,8 @@ export type AssertTrue<T extends true> = T
|
|
|
30
30
|
export type Writeable<T> = { -readonly [P in keyof T]: T[P] }
|
|
31
31
|
export type DeepWriteable<T> = { -readonly [P in keyof T]: DeepWriteable<T[P]> }
|
|
32
32
|
|
|
33
|
+
export type Nullable<T> = { [K in keyof T]: T[K] | null }
|
|
34
|
+
|
|
33
35
|
export type Primitive = null | undefined | string | number | boolean | symbol | bigint
|
|
34
36
|
|
|
35
37
|
export type LiteralUnion<LiteralType, BaseType extends Primitive> = LiteralType | (BaseType & Record<never, never>)
|
|
@@ -134,7 +136,7 @@ export const unwrapThunk = <T>(_: T | (() => T)): T => {
|
|
|
134
136
|
}
|
|
135
137
|
}
|
|
136
138
|
|
|
137
|
-
export type NullableFieldsToOptional<T> =
|
|
139
|
+
export type NullableFieldsToOptional<T> = Types.Simplify<
|
|
138
140
|
Partial<T> & {
|
|
139
141
|
[K in keyof T as null extends T[K] ? K : never]?: Exclude<T[K], null>
|
|
140
142
|
} & {
|
|
@@ -3,7 +3,7 @@ import process from 'node:process'
|
|
|
3
3
|
|
|
4
4
|
import { WorkerError } from '@effect/platform/WorkerError'
|
|
5
5
|
import * as Runner from '@effect/platform/WorkerRunner'
|
|
6
|
-
import {
|
|
6
|
+
import { Cause } from 'effect'
|
|
7
7
|
import * as Context from 'effect/Context'
|
|
8
8
|
import * as Deferred from 'effect/Deferred'
|
|
9
9
|
import * as Effect from 'effect/Effect'
|
|
@@ -15,7 +15,7 @@ import * as Scope from 'effect/Scope'
|
|
|
15
15
|
|
|
16
16
|
const platformRunnerImpl = Runner.PlatformRunner.of({
|
|
17
17
|
[Runner.PlatformRunnerTypeId]: Runner.PlatformRunnerTypeId,
|
|
18
|
-
start<I, O>() {
|
|
18
|
+
start<I, O>(closeLatch: Deferred.Deferred<void, WorkerError>) {
|
|
19
19
|
return Effect.gen(function* () {
|
|
20
20
|
if (!process.send) {
|
|
21
21
|
return yield* new WorkerError({ reason: 'spawn', cause: new Error('not in a child process') })
|
|
@@ -27,32 +27,43 @@ const platformRunnerImpl = Runner.PlatformRunner.of({
|
|
|
27
27
|
}
|
|
28
28
|
const send = (_portId: number, message: O, _transfers?: ReadonlyArray<unknown>) =>
|
|
29
29
|
Effect.sync(() => port.postMessage([1, message] /*, transfers as any*/))
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
30
|
+
|
|
31
|
+
const run = Effect.fnUntraced(function* <A, E, R>(
|
|
32
|
+
handler: (portId: number, message: I) => Effect.Effect<A, E, R>,
|
|
33
|
+
) {
|
|
34
|
+
const runtime = (yield* Effect.interruptible(Effect.runtime<R | Scope.Scope>())).pipe(
|
|
35
|
+
Runtime.updateContext(Context.omit(Scope.Scope)),
|
|
36
|
+
) as Runtime.Runtime<R>
|
|
37
|
+
const fiberSet = yield* FiberSet.make<any, WorkerError | E>()
|
|
38
|
+
const runFork = Runtime.runFork(runtime)
|
|
39
|
+
const onExit = (exit: Exit.Exit<any, E>) => {
|
|
40
|
+
if (exit._tag === 'Failure') {
|
|
41
|
+
Deferred.unsafeDone(closeLatch, Exit.die(Cause.squash(exit.cause)))
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
port.on('message', (message: Runner.BackingRunner.Message<I>) => {
|
|
45
|
+
if (message[0] === 0) {
|
|
46
|
+
const fiber = runFork(handler(0, message[1]))
|
|
47
|
+
fiber.addObserver(onExit)
|
|
48
|
+
FiberSet.unsafeAdd(fiberSet, fiber)
|
|
49
|
+
} else {
|
|
50
|
+
Deferred.unsafeDone(closeLatch, Exit.void)
|
|
51
|
+
port.close()
|
|
52
|
+
// TODO get rid of this timeout (needs help from Tim Smart)
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
// eslint-disable-next-line unicorn/no-process-exit
|
|
55
|
+
process.exit(0)
|
|
56
|
+
}, 1000)
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
port.on('messageerror', (cause) => {
|
|
60
|
+
Deferred.unsafeDone(closeLatch, new WorkerError({ reason: 'decode', cause }))
|
|
61
|
+
})
|
|
62
|
+
port.on('error', (cause) => {
|
|
63
|
+
Deferred.unsafeDone(closeLatch, new WorkerError({ reason: 'unknown', cause }))
|
|
64
|
+
})
|
|
65
|
+
port.postMessage([0])
|
|
66
|
+
})
|
|
56
67
|
|
|
57
68
|
return { run, send }
|
|
58
69
|
})
|
package/src/node/mod.ts
CHANGED
|
@@ -14,7 +14,6 @@ import { makeNoopTracer } from '../NoopTracer.js'
|
|
|
14
14
|
// import { tapCauseLogPretty } from '../effect/Effect.js'
|
|
15
15
|
|
|
16
16
|
export * as Cli from '@effect/cli'
|
|
17
|
-
export * as PlatformBun from '@effect/platform-bun'
|
|
18
17
|
export * as PlatformNode from '@effect/platform-node'
|
|
19
18
|
export * as SocketServer from '@effect/experimental/SocketServer'
|
|
20
19
|
export * as OtelResource from '@effect/opentelemetry/Resource'
|
|
@@ -52,8 +51,7 @@ export const OtelLiveHttp = ({
|
|
|
52
51
|
> =>
|
|
53
52
|
Effect.gen(function* () {
|
|
54
53
|
const config = yield* Config.all({
|
|
55
|
-
|
|
56
|
-
exporterUrlMracing: Config.string('OTEL_EXPORTER_OTLP_METRICS_ENDPOINT'),
|
|
54
|
+
exporterUrl: Config.string('OTEL_EXPORTER_OTLP_ENDPOINT'),
|
|
57
55
|
serviceName: serviceName
|
|
58
56
|
? Config.succeed(serviceName)
|
|
59
57
|
: Config.string('OTEL_SERVICE_NAME').pipe(Config.withDefault('overtone-node-utils-default-service')),
|
|
@@ -65,7 +63,7 @@ export const OtelLiveHttp = ({
|
|
|
65
63
|
const resource = { serviceName: config.serviceName }
|
|
66
64
|
|
|
67
65
|
// METRICS
|
|
68
|
-
const metricExporter = new OTLPMetricExporter({ url: config.
|
|
66
|
+
const metricExporter = new OTLPMetricExporter({ url: `${config.exporterUrl}/v1/metrics` })
|
|
69
67
|
|
|
70
68
|
const metricReader = new PeriodicExportingMetricReader({
|
|
71
69
|
exporter: metricExporter,
|
|
@@ -76,7 +74,9 @@ export const OtelLiveHttp = ({
|
|
|
76
74
|
const OtelLive = OtelNodeSdk.layer(() => ({
|
|
77
75
|
resource,
|
|
78
76
|
metricReader,
|
|
79
|
-
spanProcessor: new BatchSpanProcessor(
|
|
77
|
+
spanProcessor: new BatchSpanProcessor(
|
|
78
|
+
new OTLPTraceExporter({ url: `${config.exporterUrl}/v1/traces`, headers: {} }),
|
|
79
|
+
),
|
|
80
80
|
}))
|
|
81
81
|
|
|
82
82
|
const RootSpanLive = Layer.span(config.rootSpanName, {
|
|
@@ -104,7 +104,7 @@ export const logTraceUiUrlForSpan = (printMsg?: (url: string) => string) => (spa
|
|
|
104
104
|
|
|
105
105
|
export const getTracingBackendUrl = (span: otel.Span) =>
|
|
106
106
|
Effect.gen(function* () {
|
|
107
|
-
const endpoint = yield* Config.string('
|
|
107
|
+
const endpoint = yield* Config.string('GRAFANA_ENDPOINT').pipe(Config.option, Effect.orDie)
|
|
108
108
|
if (endpoint._tag === 'None') return
|
|
109
109
|
|
|
110
110
|
const traceId = span.spanContext().traceId
|
package/tsconfig.json
CHANGED