Skip to content

Instantly share code, notes, and snippets.

@abrahamy
Created August 3, 2024 20:18
Show Gist options
  • Save abrahamy/bc339e6403a6a54ef9469972885a019e to your computer and use it in GitHub Desktop.
Save abrahamy/bc339e6403a6a54ef9469972885a019e to your computer and use it in GitHub Desktop.
import { make } from "@effect/platform/Template";
import { SqlClient } from "@effect/sql";
import { Array, Context, Effect, Layer, pipe, Stream } from "effect";
interface EmailMessage {
contents: string;
recipients: string | string[];
}
const makeLiveEmailService = Effect.gen(function* () {
const sql = yield* SqlClient.SqlClient;
const getContactsForBroadcast = (recipients: string[]) =>
sql<{ email: string }>`SELECT * FROM contacts WHERE email ${sql.in(
recipients,
)}`.stream.pipe(Stream.map((row) => row.email));
const sendEmail = (recipient: string, email: EmailMessage) =>
Effect.gen(function* () {
// Send the email
});
return {
processAndSendEmails: (email: EmailMessage) =>
pipe(
email.recipients,
Array.ensure,
getContactsForBroadcast,
Stream.mapEffect((contact) => sendEmail(contact, email), {
concurrency: 4,
}),
Stream.runDrain,
sql.withTransaction,
),
};
});
const makeNoopEmailService = Effect.gen(function* () {
return {
processAndSendEmails: (email: EmailMessage) =>
Effect.logInfo("Sent email", email),
};
});
export class EmailService extends Context.Tag("EmailService")<
EmailService,
Effect.Effect.Success<typeof makeLiveEmailService>
>() {
static readonly live = Layer.effect(this, makeLiveEmailService);
static readonly noop = Layer.effect(this, makeNoopEmailService);
}
// Elsewhere...
const mainProgram = Effect.gen(function* () {
const emailService = yield* EmailService;
yield* emailService.processAndSendEmails({
contents: "Hello, world!",
recipients: ["[email protected]"],
});
});
// Example of dependency injection for prod vs test/dev
const runLiveProgram = mainProgram.pipe(Effect.provide(EmailService.live));
const runTestProgram = mainProgram.pipe(Effect.provide(EmailService.noop));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment