Much like Context.mergeAll (25)
it is possible to merge many layers together with a single call.
This is particularly helpful when all of the layers have requirements of never. For this reason, it is usually advisable to provide dependencies (with Layer.provide (34)
) as close as possible to the definition of the layer.
import { Effect, Layer } from "effect";import { PizzaRepository, Basket, AddressFinder, OrderService } from "./lib";
const AppLive = Layer.mergeAll( PizzaRepository.Live, Basket.Live, AddressFinder.Live, OrderService.Live);
const business = Effect.gen(function* () { const addresses = yield* AddressFinder.search("10 Downing Street"); const allPizzas = yield* PizzaRepository.all; yield* Basket.addToBasket(allPizzas[0]); yield* Basket.addToBasket(allPizzas[1]); yield* Basket.addToBasket(allPizzas[1]); yield* OrderService.placeOrder({ basket: yield* Basket.contents, deliveryAddress: addresses[0], });});
business.pipe(Effect.provide(AppLive), Effect.runPromise);If you pass two arguments to Layer.mergeAll then it behaves the same as Layer.merge (33)
.
Here is one possible implementation of Layer.mergeAll using Layer.merge (33)
and Layer.empty (35)
. The type signatures here are simplified for readability. The real implementation plucks the success, error and context parameters from each item in the context.
const mergeAll = (...layers: Layer.Layer<any, any, any>[]) => layers.reduce(Layer.merge, Layer.empty as Layer.Layer<any, never, never>);The real implementation differs in one other key way: it will run each constructor concurrently. We have not talked much about concurrency so far. This concurrency is particularly important when building layers, because this may take a while.
Layers are memoized by default. Consider the example above, where PizzaRepository.Live and OrderService.Live are both built on top of Database.Live. The database service will only be initialised once - which is a good thing, as it may need to make network calls to establish a connection.
It is also worth noting that the Layer will fail if any of the Layers passed in fails to build. In some cases this may be acceptable, but you may want a more robust strategy. In the next lesson we will see how to deal with errors running a Layer.
Let’s recap
- There are multiple ways to combine Layers
- Layer.mergeAll runs many constructors concurrently
- The combined Layer will fail if any of its arguments fails to build