Matrix protocol in OCaml, Eio specialised
1(** Eio-idiomatic errors for Matrix operations.
2
3 This module provides error types that follow Eio conventions,
4 using [Eio.Io] for IO-related errors and exceptions for
5 exceptional conditions. *)
6
7(** The source type for Matrix IO errors *)
8type err =
9 | Network of string (** Network-level error *)
10 | Http of { status : int; body : string } (** HTTP error response *)
11 | Json of string (** JSON encoding/decoding error *)
12 | Matrix of {
13 errcode : Matrix_client.Error.errcode;
14 error : string;
15 retry_after_ms : int option;
16 } (** Matrix protocol error *)
17 | Not_logged_in (** Operation requires authentication *)
18 | Cancelled (** Operation was cancelled *)
19
20type Eio.Exn.err += E of err
21
22let err e = Eio.Exn.create (E e)
23
24(** Pretty-print an error source *)
25let pp_err fmt = function
26 | Network msg -> Format.fprintf fmt "Network error: %s" msg
27 | Http { status; body } -> Format.fprintf fmt "HTTP %d: %s" status body
28 | Json msg -> Format.fprintf fmt "JSON error: %s" msg
29 | Matrix { errcode; error; _ } ->
30 Format.fprintf fmt "Matrix error %s: %s"
31 (Matrix_client.Error.errcode_to_string errcode) error
32 | Not_logged_in -> Format.fprintf fmt "Not logged in"
33 | Cancelled -> Format.fprintf fmt "Operation cancelled"
34
35let () = Eio.Exn.register_pp (fun fmt -> function
36 | E e -> pp_err fmt e; true
37 | _ -> false)
38
39(** Convert a matrix_client error to an Eio error *)
40let of_client_error = function
41 | Matrix_client.Error.Matrix_error e ->
42 Matrix {
43 errcode = e.errcode;
44 error = e.error;
45 retry_after_ms = e.retry_after_ms;
46 }
47 | Matrix_client.Error.Network_error msg -> Network msg
48 | Matrix_client.Error.Json_error msg -> Json msg
49 | Matrix_client.Error.Http_error { status; body } -> Http { status; body }
50
51(** Raise an Eio.Io exception from a matrix_client error *)
52let raise_client_error e =
53 raise (Eio.Exn.create (E (of_client_error e)))
54
55(** Convert Result-based client operations to Eio-style exceptions *)
56let unwrap = function
57 | Ok v -> v
58 | Error e -> raise_client_error e
59
60(** Check if an error is retryable *)
61let is_retryable = function
62 | Network _ -> true
63 | Http { status; _ } -> status >= 500 || status = 429
64 | Matrix { errcode; _ } -> errcode = Matrix_client.Error.M_LIMIT_EXCEEDED
65 | Json _ | Not_logged_in | Cancelled -> false
66
67(** Get retry delay in seconds from an error, if available *)
68let retry_after = function
69 | Matrix { retry_after_ms = Some ms; _ } -> Some (float_of_int ms /. 1000.0)
70 | Http { status = 429; _ } -> Some 1.0 (* Default retry after *)
71 | _ -> None