(** Eio-idiomatic errors for Matrix operations. This module provides error types that follow Eio conventions, using [Eio.Io] for IO-related errors and exceptions for exceptional conditions. *) (** The source type for Matrix IO errors *) type err = | Network of string (** Network-level error *) | Http of { status : int; body : string } (** HTTP error response *) | Json of string (** JSON encoding/decoding error *) | Matrix of { errcode : Matrix_client.Error.errcode; error : string; retry_after_ms : int option; } (** Matrix protocol error *) | Not_logged_in (** Operation requires authentication *) | Cancelled (** Operation was cancelled *) type Eio.Exn.err += E of err let err e = Eio.Exn.create (E e) (** Pretty-print an error source *) let pp_err fmt = function | Network msg -> Format.fprintf fmt "Network error: %s" msg | Http { status; body } -> Format.fprintf fmt "HTTP %d: %s" status body | Json msg -> Format.fprintf fmt "JSON error: %s" msg | Matrix { errcode; error; _ } -> Format.fprintf fmt "Matrix error %s: %s" (Matrix_client.Error.errcode_to_string errcode) error | Not_logged_in -> Format.fprintf fmt "Not logged in" | Cancelled -> Format.fprintf fmt "Operation cancelled" let () = Eio.Exn.register_pp (fun fmt -> function | E e -> pp_err fmt e; true | _ -> false) (** Convert a matrix_client error to an Eio error *) let of_client_error = function | Matrix_client.Error.Matrix_error e -> Matrix { errcode = e.errcode; error = e.error; retry_after_ms = e.retry_after_ms; } | Matrix_client.Error.Network_error msg -> Network msg | Matrix_client.Error.Json_error msg -> Json msg | Matrix_client.Error.Http_error { status; body } -> Http { status; body } (** Raise an Eio.Io exception from a matrix_client error *) let raise_client_error e = raise (Eio.Exn.create (E (of_client_error e))) (** Convert Result-based client operations to Eio-style exceptions *) let unwrap = function | Ok v -> v | Error e -> raise_client_error e (** Check if an error is retryable *) let is_retryable = function | Network _ -> true | Http { status; _ } -> status >= 500 || status = 429 | Matrix { errcode; _ } -> errcode = Matrix_client.Error.M_LIMIT_EXCEEDED | Json _ | Not_logged_in | Cancelled -> false (** Get retry delay in seconds from an error, if available *) let retry_after = function | Matrix { retry_after_ms = Some ms; _ } -> Some (float_of_int ms /. 1000.0) | Http { status = 429; _ } -> Some 1.0 (* Default retry after *) | _ -> None