Last active
March 16, 2022 20:24
-
-
Save mattiamanzati/a0a0519ce16b004ee243817343916c7c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Just a fake NodeJS db api exposed by mysql, mssql, etc...*/ | |
interface FakeTrans {} | |
interface FakeConnection { | |
query(sql: string, trans?: FakeTrans): Promise<ResultSet>; | |
beginTransaction(): Promise<FakeTrans>; | |
commitTransaction(trans: FakeTrans): Promise<void>; | |
rollbackTransaction(trans: FakeTrans): Promise<void>; | |
close(): Promise<void>; | |
} | |
declare function fakeConnect(): Promise<FakeConnection>; | |
/* The domain of errors and result of the DB service */ | |
type QueryError = unknown; | |
type ConnectionError = unknown; | |
type ResultSet = any[][]; | |
class OpenConnection extends CS.Tagged("OpenConnection")<{ | |
connection: FakeConnection; | |
}> {} | |
class OpenTransaction extends CS.Tagged("OpenTransaction")<{ | |
connection: FakeConnection; | |
transaction: FakeTrans; | |
}> {} | |
type Connection = OpenConnection | OpenTransaction; | |
const Connection = tag<Connection>(); | |
function withConnection<R, E, A>( | |
eff: T.Effect<R & Has<Connection>, E, A> | |
): T.Effect<R, ConnectionError | E, A> { | |
return T.bracketExit_( | |
T.promise(fakeConnect), | |
(connection) => | |
T.provideService(Connection)(new OpenConnection({ connection }))(eff), | |
(connection, exit) => T.promise(connection.close) | |
); | |
} | |
function query(sql: string): T.Effect<Has<Connection>, QueryError, ResultSet> { | |
return T.accessServiceM(Connection)((state) => { | |
if (state._tag === "OpenConnection") | |
return T.promise(() => state.connection.query(sql)); | |
return T.promise(() => state.connection.query(sql, state.transaction)); | |
}); | |
} | |
function transaction<R, E, A>( | |
eff: T.Effect<R & Has<Connection>, E, A> | |
): T.Effect<R & Has<Connection>, QueryError | E, A> { | |
return T.accessServiceM(Connection)((state) => { | |
if (state._tag === "OpenTransaction") return eff; // do not open more transactions | |
return T.bracketExit_( | |
T.promise(state.connection.beginTransaction), | |
(transaction) => | |
T.provideService_( | |
eff, | |
Connection, | |
new OpenTransaction({ connection: state.connection, transaction }) | |
), | |
(transaction, exit) => | |
exit._tag === "Failure" | |
? T.promise(() => state.connection.rollbackTransaction(transaction)) | |
: T.promise(() => state.connection.commitTransaction(transaction)) | |
); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment