Skip to content

Layer Memoization

Layer memoization allows a layer to be created once and used multiple times in the dependency graph. If we use the same layer twice:

Layer.merge(Layer.provide(L2, L1), Layer.provide(L3, L1))

then the L1 layer will be allocated only once.

One important feature of an Effect application is that layers are shared by default. This means that if the same layer is used twice, and if we provide the layer globally, the layer will only be allocated a single time. For every layer in our dependency graph, there is only one instance of it that is shared between all the layers that depend on it.

Example

For example, assume we have the three services A, B, and C. The implementation of both B and C is dependent on the A service:

1
import {
import Effect
Effect
,
import Context
Context
,
import Layer
Layer
} from "effect"
2
3
class
class A
A
extends
import Context
Context
.
const Tag: <"A">(id: "A") => <Self, Shape>() => Context.TagClass<Self, "A", Shape> namespace Tag
Tag
("A")<
class A
A
, { readonly
(property) a: number
a
: number }>() {}
4
5
class
class B
B
extends
import Context
Context
.
const Tag: <"B">(id: "B") => <Self, Shape>() => Context.TagClass<Self, "B", Shape> namespace Tag
Tag
("B")<
class B
B
, { readonly
(property) b: string
b
: string }>() {}
6
7
class
class C
C
extends
import Context
Context
.
const Tag: <"C">(id: "C") => <Self, Shape>() => Context.TagClass<Self, "C", Shape> namespace Tag
Tag
("C")<
class C
C
, { readonly
(property) c: boolean
c
: boolean }>() {}
8
9
const
const ALive: Layer.Layer<A, never, never>
ALive
=
import Layer
Layer
.
const effect: <typeof A, never, never>(tag: typeof A, effect: Effect.Effect<{ readonly a: number; }, never, never>) => Layer.Layer<A, never, never> (+1 overload)

Constructs a layer from the specified effect.

effect
(
10
class A
A
,
11
import Effect
Effect
.
const succeed: <{ a: number; }>(value: { a: number; }) => Effect.Effect<{ a: number; }, never, never>
succeed
({
(property) a: number
a
: 5 }).
(method) Pipeable.pipe<Effect.Effect<{ a: number; }, never, never>, Effect.Effect<{ a: number; }, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<{ a: number; }, never, never>) => Effect.Effect<{ a: number; }, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
12
import Effect
Effect
.
const tap: <{ a: number; }, Effect.Effect<void, never, never>>(f: (a: { a: number; }) => Effect.Effect<void, never, never>) => <E, R>(self: Effect.Effect<{ a: number; }, E, R>) => Effect.Effect<...> (+7 overloads)
tap
(() =>
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("initialized"))
13
)
14
)
15
16
const
const BLive: Layer.Layer<B, never, A>
BLive
=
import Layer
Layer
.
const effect: <typeof B, never, A>(tag: typeof B, effect: Effect.Effect<{ readonly b: string; }, never, A>) => Layer.Layer<B, never, A> (+1 overload)

Constructs a layer from the specified effect.

effect
(
17
class B
B
,
18
import Effect
Effect
.
const gen: <YieldWrap<Context.Tag<A, { readonly a: number; }>>, { b: string; }>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Context.Tag<A, { readonly a: number; }>>, { ...; }, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
19
const {
const a: number
a
} = yield*
class A
A
20
return {
(property) b: string
b
:
var String: StringConstructor (value?: any) => string

Allows manipulation and formatting of text strings and determination and location of substrings within strings.

String
(
const a: number
a
) }
21
})
22
)
23
24
const
const CLive: Layer.Layer<C, never, A>
CLive
=
import Layer
Layer
.
const effect: <typeof C, never, A>(tag: typeof C, effect: Effect.Effect<{ readonly c: boolean; }, never, A>) => Layer.Layer<C, never, A> (+1 overload)

Constructs a layer from the specified effect.

effect
(
25
class C
C
,
26
import Effect
Effect
.
const gen: <YieldWrap<Context.Tag<A, { readonly a: number; }>>, { c: boolean; }>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Context.Tag<A, { readonly a: number; }>>, { ...; }, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
27
const {
const a: number
a
} = yield*
class A
A
28
return {
(property) c: boolean
c
:
const a: number
a
> 0 }
29
})
30
)
31
32
const
const program: Effect.Effect<void, never, B | C>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Context.Tag<B, { readonly b: string; }>> | YieldWrap<Context.Tag<C, { readonly c: boolean; }>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
33
yield*
class B
B
34
yield*
class C
C
35
})
36
37
const
const runnable: Effect.Effect<void, never, never>
runnable
=
import Effect
Effect
.
const provide: <void, never, B | C, B | C, never, never>(self: Effect.Effect<void, never, B | C>, layer: Layer.Layer<B | C, never, never>) => Effect.Effect<void, never, never> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
38
const program: Effect.Effect<void, never, B | C>
program
,
39
import Layer
Layer
.
const merge: <never, never, B, never, never, C>(self: Layer.Layer<B, never, never>, that: Layer.Layer<C, never, never>) => Layer.Layer<B | C, never, never> (+1 overload)

Merges this layer with the specified layer concurrently, producing a new layer with combined input and output types.

merge
(
import Layer
Layer
.
const provide: <A, never, B, never, never, A>(self: Layer.Layer<B, never, A>, that: Layer.Layer<A, never, never>) => Layer.Layer<B, never, never> (+3 overloads)

Feeds the output services of this builder into the input of the specified builder, resulting in a new builder with the inputs of this builder as well as any leftover inputs, and the outputs of the specified builder.

provide
(
const BLive: Layer.Layer<B, never, A>
BLive
,
const ALive: Layer.Layer<A, never, never>
ALive
),
import Layer
Layer
.
const provide: <A, never, C, never, never, A>(self: Layer.Layer<C, never, A>, that: Layer.Layer<A, never, never>) => Layer.Layer<C, never, never> (+3 overloads)

Feeds the output services of this builder into the input of the specified builder, resulting in a new builder with the inputs of this builder as well as any leftover inputs, and the outputs of the specified builder.

provide
(
const CLive: Layer.Layer<C, never, A>
CLive
,
const ALive: Layer.Layer<A, never, never>
ALive
))
40
)
41
42
import Effect
Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: { readonly signal?: AbortSignal; } | undefined) => Promise<void>

Runs an `Effect` workflow, returning a `Promise` which resolves with the result of the workflow or rejects with an error.

runPromise
(
const runnable: Effect.Effect<void, never, never>
runnable
)
43
/*
44
Output:
45
timestamp=... level=INFO fiber=#2 message=initialized
46
*/

Although both BLive and CLive layers require the ALive layer, the ALive layer is instantiated only once. It is shared with both BLive and CLive.

If we don’t want to share a module, we should create a fresh, non-shared version of it through Layer.fresh.

Example

1
import {
import Effect
Effect
,
import Context
Context
,
import Layer
Layer
} from "effect"
2
3
class
class A
A
extends
import Context
Context
.
const Tag: <"A">(id: "A") => <Self, Shape>() => Context.TagClass<Self, "A", Shape> namespace Tag
Tag
("A")<
class A
A
, { readonly
(property) a: number
a
: number }>() {}
4
5
class
class B
B
extends
import Context
Context
.
const Tag: <"B">(id: "B") => <Self, Shape>() => Context.TagClass<Self, "B", Shape> namespace Tag
Tag
("B")<
class B
B
, { readonly
(property) b: string
b
: string }>() {}
6
7
class
class C
C
extends
import Context
Context
.
const Tag: <"C">(id: "C") => <Self, Shape>() => Context.TagClass<Self, "C", Shape> namespace Tag
Tag
("C")<
class C
C
, { readonly
(property) c: boolean
c
: boolean }>() {}
8
9
const
const ALive: Layer.Layer<A, never, never>
ALive
=
import Layer
Layer
.
const effect: <typeof A, never, never>(tag: typeof A, effect: Effect.Effect<{ readonly a: number; }, never, never>) => Layer.Layer<A, never, never> (+1 overload)

Constructs a layer from the specified effect.

effect
(
10
class A
A
,
11
import Effect
Effect
.
const succeed: <{ a: number; }>(value: { a: number; }) => Effect.Effect<{ a: number; }, never, never>
succeed
({
(property) a: number
a
: 5 }).
(method) Pipeable.pipe<Effect.Effect<{ a: number; }, never, never>, Effect.Effect<{ a: number; }, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<{ a: number; }, never, never>) => Effect.Effect<{ a: number; }, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
12
import Effect
Effect
.
const tap: <{ a: number; }, Effect.Effect<void, never, never>>(f: (a: { a: number; }) => Effect.Effect<void, never, never>) => <E, R>(self: Effect.Effect<{ a: number; }, E, R>) => Effect.Effect<...> (+7 overloads)
tap
(() =>
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("initialized"))
13
)
14
)
15
16
const
const BLive: Layer.Layer<B, never, A>
BLive
=
import Layer
Layer
.
const effect: <typeof B, never, A>(tag: typeof B, effect: Effect.Effect<{ readonly b: string; }, never, A>) => Layer.Layer<B, never, A> (+1 overload)

Constructs a layer from the specified effect.

effect
(
17
class B
B
,
18
import Effect
Effect
.
const gen: <YieldWrap<Context.Tag<A, { readonly a: number; }>>, { b: string; }>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Context.Tag<A, { readonly a: number; }>>, { ...; }, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
19
const {
const a: number
a
} = yield*
class A
A
20
return {
(property) b: string
b
:
var String: StringConstructor (value?: any) => string

Allows manipulation and formatting of text strings and determination and location of substrings within strings.

String
(
const a: number
a
) }
21
})
22
)
23
24
const
const CLive: Layer.Layer<C, never, A>
CLive
=
import Layer
Layer
.
const effect: <typeof C, never, A>(tag: typeof C, effect: Effect.Effect<{ readonly c: boolean; }, never, A>) => Layer.Layer<C, never, A> (+1 overload)

Constructs a layer from the specified effect.

effect
(
25
class C
C
,
26
import Effect
Effect
.
const gen: <YieldWrap<Context.Tag<A, { readonly a: number; }>>, { c: boolean; }>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Context.Tag<A, { readonly a: number; }>>, { ...; }, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
27
const {
const a: number
a
} = yield*
class A
A
28
return {
(property) c: boolean
c
:
const a: number
a
> 0 }
29
})
30
)
31
32
const
const program: Effect.Effect<void, never, B | C>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Context.Tag<B, { readonly b: string; }>> | YieldWrap<Context.Tag<C, { readonly c: boolean; }>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
33
yield*
class B
B
34
yield*
class C
C
35
})
36
37
const
const runnable: Effect.Effect<void, never, never>
runnable
=
import Effect
Effect
.
const provide: <void, never, B | C, B | C, never, never>(self: Effect.Effect<void, never, B | C>, layer: Layer.Layer<B | C, never, never>) => Effect.Effect<void, never, never> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
38
const program: Effect.Effect<void, never, B | C>
program
,
39
import Layer
Layer
.
const merge: <never, never, B, never, never, C>(self: Layer.Layer<B, never, never>, that: Layer.Layer<C, never, never>) => Layer.Layer<B | C, never, never> (+1 overload)

Merges this layer with the specified layer concurrently, producing a new layer with combined input and output types.

merge
(
40
import Layer
Layer
.
const provide: <A, never, B, never, never, A>(self: Layer.Layer<B, never, A>, that: Layer.Layer<A, never, never>) => Layer.Layer<B, never, never> (+3 overloads)

Feeds the output services of this builder into the input of the specified builder, resulting in a new builder with the inputs of this builder as well as any leftover inputs, and the outputs of the specified builder.

provide
(
const BLive: Layer.Layer<B, never, A>
BLive
,
import Layer
Layer
.
const fresh: <A, never, never>(self: Layer.Layer<A, never, never>) => Layer.Layer<A, never, never>

Creates a fresh version of this layer that will not be shared.

fresh
(
const ALive: Layer.Layer<A, never, never>
ALive
)),
41
import Layer
Layer
.
const provide: <A, never, C, never, never, A>(self: Layer.Layer<C, never, A>, that: Layer.Layer<A, never, never>) => Layer.Layer<C, never, never> (+3 overloads)

Feeds the output services of this builder into the input of the specified builder, resulting in a new builder with the inputs of this builder as well as any leftover inputs, and the outputs of the specified builder.

provide
(
const CLive: Layer.Layer<C, never, A>
CLive
,
import Layer
Layer
.
const fresh: <A, never, never>(self: Layer.Layer<A, never, never>) => Layer.Layer<A, never, never>

Creates a fresh version of this layer that will not be shared.

fresh
(
const ALive: Layer.Layer<A, never, never>
ALive
))
42
)
43
)
44
45
import Effect
Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: { readonly signal?: AbortSignal; } | undefined) => Promise<void>

Runs an `Effect` workflow, returning a `Promise` which resolves with the result of the workflow or rejects with an error.

runPromise
(
const runnable: Effect.Effect<void, never, never>
runnable
)
46
/*
47
Output:
48
timestamp=... level=INFO fiber=#2 message=initialized
49
timestamp=... level=INFO fiber=#3 message=initialized
50
*/

If we don’t provide a layer globally but instead provide them locally, that layer doesn’t support memoization by default.

Example

In the following example, we provided the ALive layer two times locally, and Effect doesn’t memoize the construction of the ALive layer. So, it will be initialized two times:

1
import {
import Effect
Effect
,
import Context
Context
,
import Layer
Layer
} from "effect"
2
3
class
class A
A
extends
import Context
Context
.
const Tag: <"A">(id: "A") => <Self, Shape>() => Context.TagClass<Self, "A", Shape> namespace Tag
Tag
("A")<
class A
A
, { readonly
(property) a: number
a
: number }>() {}
4
5
const
const Alive: Layer.Layer<A, never, never>
Alive
=
import Layer
Layer
.
const effect: <typeof A, never, never>(tag: typeof A, effect: Effect.Effect<{ readonly a: number; }, never, never>) => Layer.Layer<A, never, never> (+1 overload)

Constructs a layer from the specified effect.

effect
(
6
class A
A
,
7
import Effect
Effect
.
const succeed: <{ a: number; }>(value: { a: number; }) => Effect.Effect<{ a: number; }, never, never>
succeed
({
(property) a: number
a
: 5 }).
(method) Pipeable.pipe<Effect.Effect<{ a: number; }, never, never>, Effect.Effect<{ a: number; }, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<{ a: number; }, never, never>) => Effect.Effect<{ a: number; }, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
8
import Effect
Effect
.
const tap: <{ a: number; }, Effect.Effect<void, never, never>>(f: (a: { a: number; }) => Effect.Effect<void, never, never>) => <E, R>(self: Effect.Effect<{ a: number; }, E, R>) => Effect.Effect<...> (+7 overloads)
tap
(() =>
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("initialized"))
9
)
10
)
11
12
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<{ readonly a: number; }, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<{ readonly a: number; }, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
13
yield*
import Effect
Effect
.
const provide: <{ readonly a: number; }, never, A, A, never, never>(self: Effect.Effect<{ readonly a: number; }, never, A>, layer: Layer.Layer<A, never, never>) => Effect.Effect<{ readonly a: number; }, never, never> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
class A
A
,
const Alive: Layer.Layer<A, never, never>
Alive
)
14
yield*
import Effect
Effect
.
const provide: <{ readonly a: number; }, never, A, A, never, never>(self: Effect.Effect<{ readonly a: number; }, never, A>, layer: Layer.Layer<A, never, never>) => Effect.Effect<{ readonly a: number; }, never, never> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
class A
A
,
const Alive: Layer.Layer<A, never, never>
Alive
)
15
})
16
17
import Effect
Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: { readonly signal?: AbortSignal; } | undefined) => Promise<void>

Runs an `Effect` workflow, returning a `Promise` which resolves with the result of the workflow or rejects with an error.

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
18
/*
19
Output:
20
timestamp=... level=INFO fiber=#0 message=initialized
21
timestamp=... level=INFO fiber=#0 message=initialized
22
*/

We can memoize a layer manually using the Layer.memoize function. It will return a scoped effect that, if evaluated, will return the lazily computed result of this layer.

Example

1
import {
import Effect
Effect
,
import Context
Context
,
import Layer
Layer
} from "effect"
2
3
class
class A
A
extends
import Context
Context
.
const Tag: <"A">(id: "A") => <Self, Shape>() => Context.TagClass<Self, "A", Shape> namespace Tag
Tag
("A")<
class A
A
, { readonly
(property) a: number
a
: number }>() {}
4
5
const
const ALive: Layer.Layer<A, never, never>
ALive
=
import Layer
Layer
.
const effect: <typeof A, never, never>(tag: typeof A, effect: Effect.Effect<{ readonly a: number; }, never, never>) => Layer.Layer<A, never, never> (+1 overload)

Constructs a layer from the specified effect.

effect
(
6
class A
A
,
7
import Effect
Effect
.
const succeed: <{ a: number; }>(value: { a: number; }) => Effect.Effect<{ a: number; }, never, never>
succeed
({
(property) a: number
a
: 5 }).
(method) Pipeable.pipe<Effect.Effect<{ a: number; }, never, never>, Effect.Effect<{ a: number; }, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<{ a: number; }, never, never>) => Effect.Effect<{ a: number; }, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
8
import Effect
Effect
.
const tap: <{ a: number; }, Effect.Effect<void, never, never>>(f: (a: { a: number; }) => Effect.Effect<void, never, never>) => <E, R>(self: Effect.Effect<{ a: number; }, E, R>) => Effect.Effect<...> (+7 overloads)
tap
(() =>
import Effect
Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using `Cause` instances. To adjust the log level, use the `Logger.withMinimumLogLevel` function.

log
("initialized"))
9
)
10
)
11
12
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const scoped: <void, never, Scope>(effect: Effect.Effect<void, never, Scope>) => Effect.Effect<void, never, never>

Scopes all resources used in this workflow to the lifetime of the workflow, ensuring that their finalizers are run as soon as this workflow completes execution, whether by success, failure, or interruption.

scoped
(
13
import Layer
Layer
.
const memoize: <never, never, A>(self: Layer.Layer<A, never, never>) => Effect.Effect<Layer.Layer<A, never, never>, never, Scope>

Returns a scoped effect that, if evaluated, will return the lazily computed result of this layer.

memoize
(
const ALive: Layer.Layer<A, never, never>
ALive
).
(method) Pipeable.pipe<Effect.Effect<Layer.Layer<A, never, never>, never, Scope>, Effect.Effect<void, never, Scope>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<Layer.Layer<A, never, never>, never, Scope>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
14
import Effect
Effect
.
const andThen: <Layer.Layer<A, never, never>, Effect.Effect<void, never, never>>(f: (a: Layer.Layer<A, never, never>) => Effect.Effect<void, never, never>) => <E, R>(self: Effect.Effect<...>) => Effect.Effect<...> (+3 overloads)

Executes a sequence of two actions, typically two `Effect`s, where the second action can depend on the result of the first action. The `that` action can take various forms: - a value - a function returning a value - a promise - a function returning a promise - an effect - a function returning an effect

andThen
((
(parameter) memoized: Layer.Layer<A, never, never>
memoized
) =>
15
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<{ readonly a: number; }, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<{ readonly a: number; }, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
16
yield*
import Effect
Effect
.
const provide: <{ readonly a: number; }, never, A, A, never, never>(self: Effect.Effect<{ readonly a: number; }, never, A>, layer: Layer.Layer<A, never, never>) => Effect.Effect<{ readonly a: number; }, never, never> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
class A
A
,
(parameter) memoized: Layer.Layer<A, never, never>
memoized
)
17
yield*
import Effect
Effect
.
const provide: <{ readonly a: number; }, never, A, A, never, never>(self: Effect.Effect<{ readonly a: number; }, never, A>, layer: Layer.Layer<A, never, never>) => Effect.Effect<{ readonly a: number; }, never, never> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
class A
A
,
(parameter) memoized: Layer.Layer<A, never, never>
memoized
)
18
})
19
)
20
)
21
)
22
23
import Effect
Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: { readonly signal?: AbortSignal; } | undefined) => Promise<void>

Runs an `Effect` workflow, returning a `Promise` which resolves with the result of the workflow or rejects with an error.

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
24
/*
25
Output:
26
timestamp=... level=INFO fiber=#0 message=initialized
27
*/