Created
December 15, 2024 13:16
-
-
Save adept/9088e2a80e7066b1af6388c021488892 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
module Jdbc : sig | |
type 'a connection | |
val connect : config:string -> [`regular] connection | |
(* execute sql statement, like "CREATE TABLE ..." *) | |
val execute : _ connection -> string -> unit | |
val query : _ connection -> string -> string list | |
(* wraps [f] in BEGIN ... END, does error handling/cleanup *) | |
val in_transaction : [`regular] connection -> f:([`in_transaction] connection -> 'a) -> 'a | |
end = struct | |
type 'a connection = Connection | |
type row = string list | |
let connect ~config = Connection | |
let execute connection sql_statement = print_endline sql_statement | |
let query connection sql = print_endline sql; ["fake";"results"] | |
let in_transaction connection ~f = | |
execute connection "BEGIN"; | |
let result = f (connection :> [`in_transaction] connection) in | |
execute connection "COMMIT"; | |
result | |
end | |
module Account_management : sig | |
(* IMPORTANT: always do these in transaction! *) | |
val process1 : [`in_transaction] Jdbc.connection -> unit | |
val process2 : [`in_transaction] Jdbc.connection -> unit | |
(* IMPORTANT: This will fail to run in transaction! *) | |
val update_report1 : [`regular] Jdbc.connection -> unit | |
(* Ok to run either in transaction, or outside of one *) | |
val report2 : _ Jdbc.connection -> string list | |
end = struct | |
let process1 conn = | |
Jdbc.execute conn "update accounts set ..."; | |
Jdbc.execute conn "update orders set ..."; | |
Jdbc.execute conn "update balances set ..." | |
let process2 conn = | |
Jdbc.execute conn "update accounts set ..."; | |
Jdbc.execute conn "update orders set ..." | |
let update_report1 conn = | |
Jdbc.execute conn "refresh materialized view concurrently report1" | |
let report2 conn = | |
Jdbc.query conn "select sum(amount) from balances" | |
end | |
let () = | |
let open Jdbc in | |
let open Account_management in | |
let conn = connect ~config:"jdbc://dbhost/dbname" in | |
(* FIXED: User forgot to run the [process1] in transaction :( *) | |
in_transaction conn ~f:(fun conn -> | |
process1 conn); | |
(* This is actually fine *) | |
update_report1 conn; | |
in_transaction conn ~f:(fun conn -> | |
process2 conn; | |
List.iter print_endline (report2 conn)); | |
(* FIXED: user does nested transactions, but our database does not support them. *) | |
in_transaction conn ~f:(fun conn -> | |
process1 conn; | |
process2 conn); | |
(* FIXED: Report1 cannot be ran in transaction! *) | |
update_report1 conn | |
;; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment