Effect CommunityEC
Effect Community4mo ago
5 replies
BrokenSwing

Avoid leaking WorkflowEngine dependency when using a workflow in an effect

Hi, I have another question. I have defined a service to send emails:
export class Emails extends Effect.Service<Emails>()("Emails", {
  effect: Effect.gen(function* () {
    const uuid = yield* Uuid;

    const send = <T extends TemplateName>( // requires a WorkflowEngine
      email: typeof TemplateFreeEmailSpec.Type,
      template: T,
      data: TemplateData<T>
    ) =>
      Effect.gen(function* () {
        const id = yield* uuid.generate;
        yield* Effect.annotateCurrentSpan("email.uuid", id);
        yield* SendEmail.execute(
          {
            uuid: id,
            ...email,
            template,
            templateData: data,
          },
          {
            discard: true,
          }
        );
      }).pipe(Effect.withSpan("Emails::send"));

    return { send } as const;
  }).pipe(Effect.annotateSpans("service", "emails")),
  dependencies: [Uuid.Default],
}) { }


Ad you can see the default implementation calls a workflow, making the signature of the Effect send require a WorkflowEngine because of SendEmail.execute. This leaks out the fact that I depend on the WorkflowEngine. Ideally, like other services dependencies I would like this dependency to be marked at the layer level. I could not find how to do that, except maybe doing something like:
export class Emails extends Effect.Service<Emails>()("Emails", {
  effect: Effect.gen(function* () {
    const uuid = yield* Uuid;
    const worflowEngine = yield* WorkflowEngine.WorkflowEngine;

    const send = <T extends TemplateName>(
      email: typeof TemplateFreeEmailSpec.Type,
      template: T,
      data: TemplateData<T>
    ) =>
      Effect.gen(function* () {
          // ...
      }).pipe(
          Effect.withSpan("Emails::send"), 
          Effect.provideService(WorkflowEngine.WorkflowEngine, worflowEngine)
      );

    return { send } as const;
  }).pipe(Effect.annotateSpans("service", "emails")),
  dependencies: [Uuid.Default],
}) { }

Is it the way?
Was this page helpful?