Warning: Effeck is v0. The language will change in major, breaking ways. It is not suitable for production use.

C. Every Effect feature in Effeck

Effeck
const Port = Config.withDefault(Config.Port("PORT"), 3000)      // unchanged by design: Effect's API, as is

function loadUser(id: string) {
  return retry(Users.find(id), { times: 3 })        // changed: the program is a function
}

Every section of Effect 4's documentation, the Effect 3 pages that version 4 dropped, and the effect@4.0.5 modules the site omits (HTTP, SQL, CLI, AI, cluster, workflow, RPC), mapped to Effeck. Changed means Effeck has its own form. Unchanged by design means you use Effect's API as you do today, on purpose: the call rule (Chapter 13) makes Effect's API work directly, and a second way to do the same thing would be ceremony. The map comes from the feature-coverage audit (docs/research/effect-feature-coverage.md, 309 features), updated to the decisions in Chapter 29. D57 completes partial annotations with explicit infer slots.

C1. Getting started: the Effect type, creating, running, generators, pipelines

FeatureIn EffeckForm
The Effect<A, E, R> typeChangedInferred for every function; written as a return annotation to have it checked (Chapter 2)
Type helpers (Effect.Success, Error, Services)Unchanged by designApply them to the TypeScript type of an Effeck function
Annotate one channel, infer the restChanged (D57)In a return annotation with a body, write Effect<A, infer E, infer R>; all three slots are required
InstallationChangedeffect@4.0.5, effeck-runtime, and effeck (Chapter 28)
Importing EffectChangedEvery module of effect's root needs no import (D146); subpath packages such as effect/http are imported
Effect.succeedChangedreturn 42
Effect.fail, failSyncChangedthrow new HttpError()
Effect.sync around a side effectChangedCall the code; platform side effects go through Effect modules (Chapter 11), or the sync hatch (D148)
Effect.try, tryPromise, promiseChangedThe hatches try(…) and sync(async () => …), whose first arguments are self-contained TypeScript that takes values as inputs (D148, D229)
Effect.suspendChangedA call passed by name where a program is expected, or () => … (D147)
Effect.callbackChangedThe hatch callback((resume, signal) => …): resume(value), resume.fail(error); inputs come before resume (D43, D148, D230)
Effect.void, never, yieldNow, interruptChangedBare functions: yieldNow(), interrupt() (D179)
Runners (runPromise, runSync, runFork, runCallback)ChangedIn the prelude; runPromise(main()) from TypeScript, a top-level call, or a hatch's body, where no fiber runs the code (EK1005, D38, D148)
Effect.gen and yield*ChangedAn ordinary function body, and calls (Chapter 2); Effect.gen in .effeck is EK1002
Effect.gen({ self: this }, …)ChangedAn ordinary method; this keeps its JavaScript meaning
Effect.fn, fnUntracedChangedfunction f() { … }, untraced unless tracing asks for spans (Chapter 28)
map, flatMap, andThen, tap, asChangedStatements
pipe and .pipe over programsChangedpipe(() => f(), Effect.retry(…), Effect.timeout(…)) (D8)
pipe over dataUnchanged by designpipe(items, Array.filter(isActive))
Effect.all, zip, zipWithChangedPrograms as functions: Effect.all([() => a(), () => b()])
Effect.fromOption, fromResult, fromNullishOrUnchanged by designconst n = Effect.fromOption(parse(x))
Control flow inside Effect.genChangedif, for, while, and early return in an ordinary function
DevtoolsChangedThe fork's language server for .effeck; @effect/tsgo stays on .ts; Effect's DevTools for fibers and spans (Chapter 28)

C2. Error management

On a cause that mixes an expected failure and a defect, Effect's operators below keep their Effect behavior, which differs from Effeck's catch; Chapter 17 lists how.

FeatureIn EffeckForm
Expected errors and defectsChangedthrow is expected; an exception no contract lists, Effect.die, and Effect.orDie are defects (Chapter 3)
A JavaScript throwChangedAlways a typed failure; Effect.die(new Error(…)) for a bug
A JavaScript catch around a throwing callChangedcatch sees expected failures only; a dead catch is EK2004 (D37)
Data.TaggedError, Data.Error, Schema.TaggedErrorChangederror E { ... } declares a TaggedError class; Schema.TaggedError is unchanged
Error tracking in EChangedInferred: what a function throws, plus its callees' E, minus what it catches
Effect.catch, catchTag, catchTags, catchIfChangedtry/catch with narrowing; the combinators still work with a program
catchReason, catchReasons, unwrapReasonChangedNarrow e._tag and e.reason._tag inside catch
Effect.die, orDie, catchDefect, catchCause, tapDefectChangedThe same functions with a program: Effect.orDie(() => f())
Effect.result, option, exitChangedEffect.result(() => task())
orElseSucceed, firstSuccessOfChangedtry/catch, or Effect.firstSuccessOf([() => a(), () => b()])
Effect.match, matchEffect, matchCauseChangedtry with statements; Effect.exit(() => f()), then Exit.match
Effect.ignore, ignoreCauseChangedEffect.ignore(() => task())
Effect.retry, retryOrElseChangedEffect.retry(() => request(), { times: 5 }), with fresh locals per attempt
Effect.timeout, timeoutOption, timeoutOrElseChangedEffect.timeout(() => task(), "1 second"); E gains Cause.TimeoutError
Effect.sandboxChangedEffect.sandbox(() => task()) inside try; catch (cause) gets the cause
Effect.validate, partitionUnchanged by designThe same calls, with Effeck callbacks
Effect.all with mode: "result"ChangedPrograms as functions, the same options
mapError, mapBoth, tapError, flip, filterOrFailChangedcatch (e) { throw new Other({ e }) }; if (…) throw new E()
Parallel and sequential errors (Cause.reasons)Unchanged by designcatch gets the first expected failure (D28); Effect.catchCause sees all
Yieldable errorsChangedthrow new E(); new never runs anything (D24)
A contract with E = neverChangedChecked by the compiler (EK2001)

C3. Requirements management: services, layers, memoization

FeatureIn EffeckForm
Context.Service classChangedservice Users { find(id: string): User!UserNotFound } (D1, D128)
Service keysChangedDerived from package, path, and class name; duplicates are EK3001
yield* Users, then a methodChangedUsers.find(id); Users() gives the implementation
Users.use, useSyncChangedCall the member: Users.find(id)
A member that returns a plain value (Path.join)ChangedPath.join(a, b); the service joins R (D41)
A member that is an Effect valueUnchanged by designCall it: Terminal.readLine()
The make option and static layerChangedstatic make() and static readonly layer on the service class (D40)
Context.Reference with a defaultUnchanged by designContext.Reference(key, { defaultValue }) as is, or static readonly default on a service class (D40)
Effect.serviceOptionUnchanged by designEffect.serviceOption(Mailer)
Default services (Clock, Console, Random, Tracer, ConfigProvider)Unchanged by designClock.currentTimeMillis(); R stays empty
Effect.provideServiceChangedEffect.provideService(() => program(), Mailer, quiet)
Context.make, Context.addUnchanged by designValues, provided with Effect.provide(() => program(), context)
Layer.succeed, effect, syncChangedLayer.effect(Users, () => { const db = Database(); return { … } })
Layers that hold resourcesChangedAcquire without using; the layer's Scope owns the resource
Requirements that leak into methodsChangedEK3101
Layer.merge, mergeAll, provide, provideMergeUnchanged by designThe same functions; wire(…) orders them and reports graph errors (D27)
Missing, duplicate, and cyclic providersChangedEK3201, EK3202, EK3203
Effect.provideChangedEffect.provide(() => program(), AppLive); each provide builds its layers once (D21)
Layer memoization, Layer.fresh, MemoMapsUnchanged by designAs in Effect; provide at main, or run entry points through one ManagedRuntime (D21)
Layer.launch, build, unwrap, mock, tap, catchUnchanged by designValues and calls as in Effect
Fake servicesChangedLayer.succeed(Users, { find: (id) => ada, rename: () => {} })

C4. Resource management

FeatureIn EffeckForm
Effect.scopedChangedA block that declares using
acquireRelease, acquireUseReleaseChangedusing lock = Effect.acquireRelease(() => acquire(), (l) => release(l))
Interruptible acquisitionUnchanged by designacquireRelease(…, { interruptible: true }); using keeps the choice (D25)
A resource the caller ownsChangedAcquire without using; Scope stays in R (D14)
ensuring, onExit, onError, addFinalizerChangedfinally; Effect.onExit(() => f(), (exit) => …) when the exit matters
Scope.make, close, provideUnchanged by designThe same calls
Disposable resourcesChangedusing x = disposable registers [Symbol.dispose]()
RcRef, RcMap, Pool, ScopedRef, ScopedCache, LayerMapChangedusing pool = Pool.make({ acquire: () => connect(), size: 10 })
Cleanup when a handler abandons a programChangedNo Effect equivalent; using and finally run before handle returns

C5. Observability

FeatureIn EffeckForm
Effect.log and its levelsUnchanged by designEffect.logWarning("disk low")
A minimum log level for a regionChangedEffect.provideService(() => program(), References.MinimumLogLevel, "Debug")
annotateLogs, withLogSpanChangedWith a program: Effect.withLogSpan(() => handle(req), "handler")
annotateLogsScopedUnchanged by designThe same call; a using block or the caller supplies the Scope
Logger.make, Logger.layer, formats, Logger.toFileUnchanged by designValues, provided as layers
ConsoleUnchanged by designConsole.log("hi"); console.log is EK4402
Metrics (counter, gauge, histogram, summary, frequency, timer)Unchanged by designDefined at the top level; Metric.update(requests, 1)
trackSuccesses, trackDurationChangedEffect.trackDuration(() => task(), latency)
Metric.CurrentMetricAttributesChangedProvided around a program with Effect.provideService
Spans per function (Effect.fn("name"))Changed"tracing" in tsconfig.json, or Effect.withSpan where you want one (Chapter 28)
Effect.withSpanChangedEffect.withSpan(() => loadUser(id), "load-user")
annotateCurrentSpan, currentSpan, linkSpansUnchanged by designThe same calls
Logs as span eventsUnchanged by designSpans stay correct across handler capture (G6a)
Exporting traces, logs, and metrics (OtlpTracer, OtlpLogger, OtlpMetrics from effect/observability)Unchanged by designLayers, provided as in Effect: OtlpTracer.layer({ url, resource: { serviceName } })
FiberSet, FiberMap, FiberHandleChangedusing set = FiberSet.make(), then FiberSet.run(set, () => task())
Supervisors (Effect 3)Unchanged by designEffect 4 has none; FiberSet and fork

C6. Configuration

FeatureIn EffeckForm
Config.String, Port, Int, Boolean, Duration, URL, RedactedUnchanged by designData until called: const Port = Config.Port("PORT"), then Port() (D24)
Config.all, withDefault, nested, option, orElse, schemaUnchanged by designComposed as data, read once by calling
ConfigProvider (fromEnv, fromUnknown, layer)Unchanged by designProvided as a layer
ConfigProvider.fromDotEnv(), fromDir()Unchanged by designCalls that run, inside a function
config.parse(provider) in testsUnchanged by designAppConfig.parse(provider) returns an Effect, so the call runs it
A Layer chosen by config (Layer.unwrap)ChangedLayer.unwrap(() => …), with a program
RedactedUnchanged by designRedacted.value(DatabaseUrl())

C7. Runtime

FeatureIn EffeckForm
NodeRuntime.runMain, BunRuntime.runMainChangedNodeRuntime.runMain(() => main()) at a module's top level
runMain optionsChangedThe same options, with a program
One-shot runners and run*With(context)ChangedPrograms as functions, only where no fiber runs the code (D38)
ManagedRuntimeUnchanged by designManagedRuntime.make(AppLive); runtime.runPromise(() => handle(req)) in a framework callback, or from TypeScript
Top-level awaitChangedNo await; the top level builds values and calls runners (EK1001)
Scheduling and fairnessUnchanged by design2048 operations per slice; a plain JavaScript region is atomic
ErrorReporter, Effect.withErrorReportingChangedEffect.withErrorReporting(() => program()): the thunk is a program (D39)

C8. Scheduling

FeatureIn EffeckForm
Schedule constructors (spaced, fixed, exponential, recurs, cron)Unchanged by designSchedule.exponential("250 millis")
Schedule combinatorsUnchanged by design.pipe over a schedule value
Effectful schedule callbacks (tap, modifyDelay)Unchanged by designEffeck callbacks
Effect.repeatChangedEffect.repeat(() => poll(), { schedule, until: (s) => s === "done" })
Effect.retry with a scheduleChangedEffect.retry(() => f(), Schedule.exponential("100 millis"))
Effect.schedule, repeatOrElseChangedPrograms as functions
Cron.parse, Schedule.cronUnchanged by designEffect.fromResult(Cron.parse("0 3 * * *", "UTC"))
A cron job's lifetimeChangedfork(() => Effect.schedule(() => report(), Schedule.cron(cron))) inside main

C9. State management

FeatureIn EffeckForm
RefUnchanged by designconst ref = Ref.make(0); Ref.update(ref, (n) => n + 1)
Programs stored as object fieldsChangedinc = () => Ref.update(this.value, (n) => n + 1)
SynchronizedRef.updateEffectUnchanged by designSynchronizedRef.updateEffect(ref, (xs) => [...xs, load()])
SubscriptionRef.changesUnchanged by designA Stream: iterate it with for...of
Transactions (TxRef, Effect.tx)ChangedEffect.tx(() => TxRef.update(ref, (n) => n + 1))

C10. Caching

FeatureIn EffeckForm
Effect.cachedChangedconst get = Effect.cached(() => load()), then get()
cachedWithTTL, cachedInvalidateWithTTLChangedPrograms as functions; get() and invalidate()
CacheUnchanged by designCache.make({ capacity: 100, lookup: (id) => fetchUser(id) })

C11. Batching

FeatureIn EffeckForm
Request.Class, TaggedClassUnchanged by designThe same classes
RequestResolver.make, fromEffect, makeGrouped, batchNUnchanged by designCallbacks are Effeck functions
Effect.requestUnchanged by designEffect.request(new GetUser({ id }), resolver)
Batches form under concurrencyUnchanged by designSequential calls never batch, as in Effect
RequestResolver.withCacheUnchanged by designInside a function or a Layer
A resolver that needs a serviceChangedLayer.effect(Todos, () => { const http = Http(); … })

C12. Concurrency

FeatureIn EffeckForm
The concurrency optionChangedPrograms as functions, the same options
Struct and record forms of Effect.allChangedRecord fields convert to programs
A computed array of programsChangedEffect.all(stores.map(makeSync)) (D9)
Effect.forEach with concurrencyUnchanged by designThe same call
Effect.zip with concurrent: trueChangedPrograms as functions
race, raceFirst, raceAllChangedPrograms as functions; each has its own exit rule (Chapter 7)
forkChild, forkDetach, forkScoped, forkInChangedPrograms as functions
Background work owned by a blockChangedfork(() => heartbeat()) (D19)
Fiber.join, joinAllChangedjoin fiber and join [a, b] (D225)
Fiber.await, interrupt, interruptAllUnchanged by designThe same calls, or fiber.await() and fiber.interrupt()
Interruption is not an errorChangedcatch never sees it; finally and using always run
uninterruptible, uninterruptibleMask, interruptibleMaskChangeduninterruptible { … restore { … } } and interruptible { … } blocks, or the prelude functions with a program (D180)
onInterruptChangedEffect.onInterrupt(() => task(), () => Console.log("stopped"))
Effect.foreverChangedwhile (true) tick()
DeferredUnchanged by designDeferred.make<number>(), d.await() (D227)
Deferred.complete with a programChangedDeferred.complete(d, () => task())
QueueUnchanged by designQueue.offer(queue, 1)
PubSub.subscribeChangedusing subscription = PubSub.subscribe(pubsub)
PubSub.publishUnchanged by designThe same call
SemaphoreUnchanged by designSemaphore.make(1); mutex.withPermits(1)(() => task())
LatchUnchanged by designlatch.open(): an Effect member runs when called
What a forked fiber seesUnchanged by designA snapshot of the parent's Context
Control operations across fibersChangedEK4201 (Chapter 9)

C13. Async interop

FeatureIn EffeckForm
async and awaitChangedasync only inside a hatch's function, where await is JavaScript's; elsewhere a call waits, join waits for a fiber, and await appears only in the await operations (D148, D226)
Effect.promise, Effect.tryPromiseChangedsync(async (signal) => …) and try(async (signal) => …); the AbortSignal, after any inputs, cancels on interruption (D148, D230)
Effect.callbackChangedThe callback hatch; resume(value); suspend for resources (D43, D148)
Effect.runPromise from Promise codeChangedrunPromise, from TypeScript, a top-level callback, or a hatch's body (D38, D148)
Async iterables and event emittersUnchanged by designStream.fromAsyncIterable, Stream.fromEventListener
Synchronous code that throwsChangedtry(…); a dead catch is EK2004 (D37)
Effect 3 librariesChangedForeign code: try((p) => Effect3.runPromise(p), (error) => …, p)

C14. Streams

FeatureIn EffeckForm
A sequence produced by code that waits between valuesChangedA function* producer and for...of (Chapter 8)
Streams from data (make, range, fromIterable, tick)Unchanged by designStream.range(1, 10)
fromEffect, fromEffectRepeatChangedPrograms as functions
unfold, paginateUnchanged by designEffeck callbacks
Stream.callback, fromQueue, fromPubSub, fromEventListenerUnchanged by designThe same calls; inner JavaScript callbacks cannot pause (EK4301)
Operators (map, filter, mapEffect, merge, buffer, debounce, groupedWithin)Unchanged by designThe same calls; a producer converts to a Stream (D26)
runCollect, runForEach, runFold, runDrain, runUnchanged by designCalls that run the stream
Stream.toPullChangedfor...of over a Stream (D26)
Stream.catch, retry, timeoutUnchanged by designThe same calls; try/catch applies to the call that runs a stream
Stream.scopedUnchanged by designStream.scoped(stream): it takes a Stream
Stream.ensuringChangedStream.ensuring(stream, () => cleanup()): the finalizer is a program
Stream.partition, broadcastNChangedusing, because they need a Scope
Producers and streams togetherChangedA producer is a Stream wherever one is expected (D26)
Stream.toAsyncIterableUnchanged by designFrom TypeScript, with for await

C15. Sinks

FeatureIn EffeckForm
Sinks (sum, count, collect, head, drain)Unchanged by designStream.run(stream, Sink.sum)
Sink.fold, foldUntil, forEachUnchanged by designEffeck callbacks; pure ones pass as plain functions (D9)
A producer into a sinkChangedThe producer converts to a Stream (D26)

C16. Testing

FeatureIn EffeckForm
it.effectChangedit.effect("name", () => { … })
it.live, .each, .prop, it.flakyTestUnchanged by designThe same calls
layer(AppLive)("suite", (it) => …)Unchanged by designThe same call
Fake servicesChangedObject literals in Layer.succeed
An override for one regionChangedEffect.provideService(() => program(), Mailer, quiet)
Scripted answers to requestsChangedhandle (Chapter 9)
TestClockUnchanged by designTestClock.adjust("1 minute")
TestConsole, TestCryptoUnchanged by designTestConsole.logLines()
Asserting on an ExitUnchanged by designExit.succeed(1) is data (D24)
Promise-style testsChangedStay in .ts, or move to it.effect (D38)
Property testsUnchanged by designit.effect.prop, Arbitrary.checkEffect

C17. Code style

FeatureIn EffeckForm
Run once, at the edgeChangedNodeRuntime.runMain(() => main())
Avoid tacit callsUnchanged by designThe same advice
Dual APIsChangedData-first with a program; data-last inside pipe
Branded typesUnchanged by designA failed check throws a defect; Int.result(n) for a typed error
Pattern matching with pure handlers (Match)Unchanged by designThe same module
Pattern matching with effectful branchesChangedswitch or if; effectful Match handlers are EK4301 (D9)
Do notation (Effect.Do, bind, let)ChangedStatements
Control flow operators (Effect.when, whileLoop)Changedif and while

C18. Data types

FeatureIn EffeckForm
OptionUnchanged by designPlain data; Option.gen stays in .ts
An Option to a typed failureChangedEffect.fromOption(found), or throw
Result (Effect 3's Either)Unchanged by designPlain data
Effect.result, Effect.exitChangedPrograms as functions
Effect.fromResultUnchanged by designThe same call
Exit constructors and readersUnchanged by designData (D24); Exit.match
CauseUnchanged by designEffect.catchCause(() => f(), (cause) => …)
Data.Class, TaggedClass, taggedEnumUnchanged by designThe same functions
Error classesChangederror E { ... } declarations; throw
new of a class whose instances are EffectsChangednew constructs and never runs (D24)
Chunk, HashSet, HashMap, Duration, BigDecimal, RedactedUnchanged by designThe same modules
DateTimeUnchanged by designDateTime.now(); new Date() is EK4403
A time zone for a regionChangedPrograms as functions

C19. Traits and behaviours

FeatureIn EffeckForm
Equal, HashUnchanged by designThe same functions; === keeps its JavaScript meaning. A class implements [Equal.symbol] and [Hash.symbol] with plain methods (D55, Chapter 15)
Equivalence, OrderUnchanged by designThe same modules

C20. Schema

FeatureIn EffeckForm
Defining schemasUnchanged by designValues, built at the top level
decodeUnknownEffect, decodeEffect, encodeEffectUnchanged by designCalls that run; SchemaError joins E
decodeUnknownSync, is, assertsUnchanged by designTrusted; their exceptions are defects (D37)
decodeUnknownExitUnchanged by designAn Exit value (D24)
Filters and transformationsUnchanged by designThe same functions
transformEffect, checkEffectUnchanged by designEffeck callbacks
Defaults given as Effects (withConstructorDefault)ChangedA program: Schema.withConstructorDefault(() => Clock.currentTimeMillis())
Schema.Class, TaggedClassUnchanged by designThe same classes
Schema.TaggedErrorChangedthrow new HttpError({ status: 500 })
make, makeEffectUnchanged by designmake throws defects; makeEffect runs
Annotations, formatters, JSON Schema, Arbitrary, compilersUnchanged by designThe same functions
Config.schemaUnchanged by designData (D24)

C21. Platform

FeatureIn EffeckForm
Node.js and browser APIsChangedNot callable from .effeck (EK4402); Chapter 11 names each replacement
Platform layers (NodeServices.layer)ChangedEffect.provide(() => main(), NodeServices.layer)
FileSystemUnchanged by designFileSystem.readFileString(path), from effect/FileSystem
FileSystem.open (a scoped File)Changedusing file = FileSystem.open(path)
FileSystem.layerNoopChangedIts methods return values, not Effects
PathUnchanged by designPath.join(a, b); Path joins R (D41)
Terminal, StdioUnchanged by designTerminal.readLine()
Child processesUnchanged by designChildProcessSpawner.string(ChildProcess.make("git", ["status"])); the command is data (D24)
KeyValueStoreUnchanged by designFrom effect/persistence
SocketsChangedusing for a scoped reader
WorkersUnchanged by designEffeck handlers

C22. HTTP

FeatureIn EffeckForm
HttpClientUnchanged by designHttpClient.get(url) runs
Response bodiesUnchanged by designresponse.json()
Client middlewareUnchanged by design.pipe over a client value
HttpRouter.add handlersUnchanged by designA handler function, or a program (D39)
ServingChangedNodeRuntime.runMain(() => Layer.launch(HttpRouter.serve(routes)))
HttpApi definitions, middleware, securityUnchanged by designValues
HttpApi handlersUnchanged by designEffeck functions
HttpApiClientUnchanged by designCalls that run

C23. SQL

FeatureIn EffeckForm
SqlClientUnchanged by designconst sql = SqlClient.SqlClient()
sql`…` statementsUnchanged by designData until called (D24): sql`SELECT * FROM users`() runs it, and .stream stays reachable
Fragments (sql.in, sql.insert, sql.and)Unchanged by designThe same calls
sql.withTransactionChangedsql.withTransaction(() => insertAll())
SqlSchema, SqlResolver, SqlModel, migrationsUnchanged by designThe same modules
Driver layers read from configUnchanged by designConfig arguments are data (D24)

C24. CLI

FeatureIn EffeckForm
Command.make, withSubcommands, withHandlerUnchanged by designData (D24), declared at the top level
Flags and argumentsUnchanged by designValues
PromptsUnchanged by designData until called
Running a commandChangedInside main, handed to a runner

C25. AI

FeatureIn EffeckForm
LanguageModel.generateText, generateObjectUnchanged by designCalls that run
LanguageModel.streamTextUnchanged by designA Stream
Tool.make, Toolkit.makeUnchanged by designData (D24)
Tool handlersChangedtoolkit.toLayer(() => ({ search: ({ q }) => runSearch(q) }))
ChatUnchanged by designChat.empty()
Effect.withExecutionPlanChangedEffect.withExecutionPlan(() => program(), plan)
AiError reasonsChangedNarrow e.reason._tag in catch
Provider layers read from configUnchanged by designConfig arguments are data (D24)

C26. Cluster, workflow, and RPC

FeatureIn EffeckForm
Rpc.make, RpcGroup.makeUnchanged by designValues
group.toLayer(handlers)Unchanged by designAn object of Effeck handlers (D39)
RPC clients and serversChangedusing client = RpcClient.make(UserRpcs)
EntitiesUnchanged by designCounter.client()
WorkflowsUnchanged by designBodies are Effeck functions (D42)
ActivitiesUnchanged by designData until called (D24)
DurableClock.sleep, DurableDeferred.awaitUnchanged by designCalls that run
ReplayUnchanged by designEach execution is a fresh program run; held continuations end with it (D42)

C27. Effect 3 features that Effect 4 removed

FeatureIn EffeckForm
MicroUnchanged by designEffect 4 has none; Effect 3 code is foreign code (Chapter 10)
SupervisorUnchanged by designFiberSet and fork
STMUnchanged by designEffect.tx with TxRef
FiberRef, Effect.locallyChangedEffect.provideService(() => program(), References.CurrentLogLevel, "Debug")
EitherUnchanged by designResult
MailboxUnchanged by designQueue
Runtime<R>ChangedManagedRuntime, or run*With under D38
Effect.Service, Effect.Tag accessorsChangedAbstract service classes, called as Users.find(id)
withConcurrency, withClock, withRandomUnchanged by designPer-call options and References