OCaml client for the Amazon DynamoDB HTTP API (JSON 1.0 protocol).
dynamodb: request encoding, response decoding, error parsing. Items carry every DynamoDB attribute type; numbers are exact decimals. HTTP goes through the effectDynamodb.Effects.Call. Depends onyojson,base64andppx_yojson_conv.dynamodb-cohttp-eio: handles that effect with cohttp-eio, signing with sigv4.
Supported: PutItem, GetItem, DeleteItem, UpdateItem (ReturnValues = ALL_NEW), Query (all pages without limit, one page with limit), Scan (all pages), TransactWriteItems (Put / Delete).
Not supported: BatchGetItem, BatchWriteItem, IndexName, ConsistentRead, ProjectionExpression, other ReturnValues, and Update / ConditionCheck transact items.
Not on the opam repository yet.
opam pin add dynamodb https://github.com/lmdexpr/dynamodb.ml.git
opam pin add dynamodb-cohttp-eio https://github.com/lmdexpr/dynamodb.ml.gitopen Ppx_yojson_conv_lib.Yojson_conv.Primitives
type user = { pk : string; name : string } [@@deriving yojson]
let () =
Eio_main.run @@ fun env ->
let client = Cohttp_eio.Client.make ~https:None env#net in
let now () = Eio.Time.now env#clock in
let config = Dynamodb_cohttp_eio.Config.local () in
Dynamodb_cohttp_eio.run ~now ~client ~config @@ fun () ->
let db = Dynamodb.Client.make ~table:"users" in
let item = yojson_of_user { pk = "alice"; name = "Alice" } |> Dynamodb.Projection.item_of_yojson_exn in
match Dynamodb.Client.put db ~item with
| Error e -> prerr_endline (Dynamodb.Error.to_string e)
| Ok () -> (
match Dynamodb.Client.get db ~key:(Dynamodb.Item.singleton "pk" (Dynamodb.Value.String "alice")) with
| Ok (Some item) -> print_endline (Dynamodb.Projection.yojson_of_item_exn item |> user_of_yojson).name
| Ok None -> print_endline "not found"
| Error e -> prerr_endline (Dynamodb.Error.to_string e))Config.local ()targetshttp://127.0.0.1:8000;Config.aws ~regiontargets the regional endpoint over HTTPS, which needs an~httpsTLS wrapper on the cohttp-eio client.- Credentials come from
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEYor the ECS container endpoint (sigv4-cohttp-eio). - Every
Clientfunction returns(_, Dynamodb.Error.t) result.Error.is_conditional_check_failedrecognizes failed conditions, including cancelled transactions. - Expressions (
condition_expression,key_condition_expression, ...) are raw strings. Pass values throughexpression_attribute_values, never by string concatenation. Dynamodb.Action.<Name>.(make ... |> perform)is the layer underClient.Dynamodb.Transaction.writetakes items built withTransaction.put/Transaction.delete.
Handling the effect yourself, e.g. in tests:
let with_stub ~respond k =
try k ()
with effect Dynamodb.Effects.Call { action; body }, k ->
Effect.Deep.continue k (respond ~action ~body)respond returns Ok json for a 2xx body or Error body for a 4xx body.
Item.t maps names to Value.t: String, Number, Binary (raw bytes), Bool, Null, List, Map, String_set, Number_set, Binary_set. Reading an item and writing it back preserves attribute types and decimal digits.
Number.t is an exact decimal: 38 significant digits, adjusted exponent -130 to 125. Number.of_string, of_float and to_int return result; to_float may round. Set constructors reject empty sets and duplicates (1 and 1.0 are duplicates).
Projection converts to and from ordinary JSON, e.g. for [@@deriving yojson] records. Projection.item_of_yojson reads objects, arrays, strings and numbers as Map, List, String and Number. Projection.yojson_of_item takes a policy for each thing JSON cannot represent:
| Option | Default | Alternatives |
|---|---|---|
numbers |
Float: fractions round to floats, integers stay Int / Intlit |
Exact: reject fractions; String: decimal strings |
sets |
Reject |
Lists |
binary |
Reject |
Base64 |
Errors carry a path such as $["events"][0]; _exn variants raise Projection.Conversion_error. Malformed wire values in a response raise Ppx_yojson_conv_lib.Yojson_conv.Of_yojson_error with the same kind of path.
opam switch create . 5.5.1 --no-install -y
opam install dune -y
dune build
dune runtest
dune fmt