Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions packages/effect-readiness/src/AwaitCondition.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import { Schema } from 'effect'
import { Condition } from './Condition.schema.js'
import { ProbeTarget } from './ProbeTarget.schema.js'

export class AwaitCondition extends Schema.TaggedClass<AwaitCondition>()('AwaitCondition', {
target: ProbeTarget,
condition: Condition,
}) {}
export class AwaitCondition
extends Schema.TaggedClass<AwaitCondition, { readonly brand: unique symbol }>()('AwaitCondition', {
target: ProbeTarget,
condition: Condition,
})
{}
4 changes: 2 additions & 2 deletions packages/effect-readiness/src/ProbeVerdict.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ type ProbeVerdictTypeId = typeof ProbeVerdictTypeId
* `awaitCondition` hands back when the wait ends. One class, so the per-pass decision's
* success variant and the public result are the same value.
*/
export class Satisfied extends Schema.TaggedClass<Satisfied>()('Satisfied', {}) {
export class Satisfied extends Schema.TaggedClass<Satisfied, { readonly brand: unique symbol }>()('Satisfied', {}) {
readonly [ProbeVerdictTypeId] = ProbeVerdictTypeId
}

/** One pass's judgement that the condition does not hold yet; the shell polls again. */
export class NotYet extends Schema.TaggedClass<NotYet>()('NotYet', {}) {
export class NotYet extends Schema.TaggedClass<NotYet, { readonly brand: unique symbol }>()('NotYet', {}) {
readonly [ProbeVerdictTypeId] = ProbeVerdictTypeId
}

Expand Down
18 changes: 11 additions & 7 deletions packages/effect-readiness/src/ReadinessError.schema.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import { Schema } from 'effect'

export class LogSourceError extends Schema.TaggedError<LogSourceError>()('LogSourceError', {
source: Schema.String,
cause: Schema.optional(Schema.Unknown),
}) {
export class LogSourceError
extends Schema.TaggedError<LogSourceError, { readonly brand: unique symbol }>()('LogSourceError', {
source: Schema.String,
cause: Schema.optional(Schema.Unknown),
})
{
override get message(): string {
return `log source "${this.source}" failed`
}
}

/** A probe command failed to decode; the wait's own read built it, so this is a defect it surfaces. */
export class ProbeInputInvalid extends Schema.TaggedError<ProbeInputInvalid>()('ProbeInputInvalid', {
issue: Schema.String,
}) {
export class ProbeInputInvalid
extends Schema.TaggedError<ProbeInputInvalid, { readonly brand: unique symbol }>()('ProbeInputInvalid', {
issue: Schema.String,
})
{
override get message(): string {
return `The probe command did not decode: ${this.issue}`
}
Expand Down
10 changes: 6 additions & 4 deletions packages/effect-readiness/src/evaluate-probe.workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import { Condition } from './Condition.schema.js'
import { ProbeEvidence } from './ProbeEvidence.schema.js'
import { NotYet, ProbeVerdict, Satisfied } from './ProbeVerdict.schema.js'

export class EvaluateProbe extends Schema.TaggedClass<EvaluateProbe>()('EvaluateProbe', {
condition: Condition,
evidence: ProbeEvidence,
}) {
export class EvaluateProbe
extends Schema.TaggedClass<EvaluateProbe, { readonly brand: unique symbol }>()('EvaluateProbe', {
condition: Condition,
evidence: ProbeEvidence,
})
{
static readonly [Workflow.InstrumentationBrand] = {} as const
}

Expand Down
24 changes: 16 additions & 8 deletions packages/effect-readiness/src/resolve-probe.workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,44 @@ const ProbePlanTypeId: unique symbol = Symbol.for('@systemfsoftware/effect-readi
type ProbePlanTypeId = typeof ProbePlanTypeId

/** The condition names a port with no binding behind it; no host probe runs. */
export class ProbeAbsent extends Schema.TaggedClass<ProbeAbsent>()('ProbeAbsent', { guestPort: Schema.Int }) {
export class ProbeAbsent
extends Schema.TaggedClass<ProbeAbsent, { readonly brand: unique symbol }>()('ProbeAbsent', { guestPort: Schema.Int })
{
readonly [ProbePlanTypeId] = ProbePlanTypeId
}

/** The condition dials the bound host socket. */
export class ProbeTcp extends Schema.TaggedClass<ProbeTcp>()('ProbeTcp', { binding: PortBinding }) {
export class ProbeTcp
extends Schema.TaggedClass<ProbeTcp, { readonly brand: unique symbol }>()('ProbeTcp', { binding: PortBinding })
{
readonly [ProbePlanTypeId] = ProbePlanTypeId
}

/** The condition exchanges an HTTP request over the bound host socket. */
export class ProbeHttp extends Schema.TaggedClass<ProbeHttp>()('ProbeHttp', {
export class ProbeHttp extends Schema.TaggedClass<ProbeHttp, { readonly brand: unique symbol }>()('ProbeHttp', {
binding: PortBinding,
path: Schema.String,
}) {
readonly [ProbePlanTypeId] = ProbePlanTypeId
}

/** The condition reads the guest log stream for a pattern. */
export class ProbeLog extends Schema.TaggedClass<ProbeLog>()('ProbeLog', { pattern: Schema.String }) {
export class ProbeLog
extends Schema.TaggedClass<ProbeLog, { readonly brand: unique symbol }>()('ProbeLog', { pattern: Schema.String })
{
readonly [ProbePlanTypeId] = ProbePlanTypeId
}

/** The probe one condition resolves to. */
export const ProbePlan = Schema.Union([ProbeAbsent, ProbeTcp, ProbeHttp, ProbeLog])
export type ProbePlan = typeof ProbePlan.Type

export class ResolveProbe extends Schema.TaggedClass<ResolveProbe>()('ResolveProbe', {
target: ProbeTarget,
condition: Condition,
}) {
export class ResolveProbe
extends Schema.TaggedClass<ResolveProbe, { readonly brand: unique symbol }>()('ResolveProbe', {
target: ProbeTarget,
condition: Condition,
})
{
static readonly [Workflow.InstrumentationBrand] = {} as const
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ export interface LoopbackService {
}

/** The release probe fails with this when a stopped probe still holds a server connection. */
export class ConnectionLeak extends Schema.TaggedError<ConnectionLeak>()('ConnectionLeak', {
open: Schema.Int,
}) {}
export class ConnectionLeak
extends Schema.TaggedError<ConnectionLeak, { readonly brand: unique symbol }>()('ConnectionLeak', {
open: Schema.Int,
})
{}

const zeroOpenConnections = (open: () => number): Effect.Effect<void, ConnectionLeak> =>
Effect.repeat(
Expand Down
Loading