Layer.mergeAll

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