1pub fn is_retryable_kind(kind: ferriskey::ErrorKind) -> bool {
31 use ferriskey::ErrorKind::*;
32 matches!(
33 kind,
34 IoError | FatalSendError | TryAgain | BusyLoadingError | ClusterDown
35 )
36}
37
38pub fn kind_to_stable_str(kind: ferriskey::ErrorKind) -> &'static str {
49 use ferriskey::ErrorKind::*;
50 match kind {
51 ResponseError => "response_error",
52 ParseError => "parse_error",
53 AuthenticationFailed => "authentication_failed",
54 PermissionDenied => "permission_denied",
55 TypeError => "type_error",
56 ExecAbortError => "exec_abort",
57 BusyLoadingError => "busy_loading",
58 NoScriptError => "no_script",
59 InvalidClientConfig => "invalid_client_config",
60 Moved => "moved",
61 Ask => "ask",
62 TryAgain => "try_again",
63 ClusterDown => "cluster_down",
64 CrossSlot => "cross_slot",
65 MasterDown => "master_down",
66 IoError => "io_error",
67 FatalSendError => "fatal_send",
68 FatalReceiveError => "fatal_receive",
69 ClientError => "client_error",
70 ExtensionError => "extension_error",
71 ReadOnly => "read_only",
72 MasterNameNotFoundBySentinel => "master_name_not_found_by_sentinel",
73 NoValidReplicasFoundBySentinel => "no_valid_replicas_found_by_sentinel",
74 _ => "unknown",
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81 use ferriskey::ErrorKind;
82
83 #[test]
84 fn retryable_kinds_whitelist() {
85 assert!(is_retryable_kind(ErrorKind::IoError));
86 assert!(is_retryable_kind(ErrorKind::FatalSendError));
87 assert!(is_retryable_kind(ErrorKind::TryAgain));
88 assert!(is_retryable_kind(ErrorKind::BusyLoadingError));
89 assert!(is_retryable_kind(ErrorKind::ClusterDown));
90 }
91
92 #[test]
93 fn non_retryable_kinds() {
94 assert!(!is_retryable_kind(ErrorKind::FatalReceiveError));
95 assert!(!is_retryable_kind(ErrorKind::AuthenticationFailed));
96 assert!(!is_retryable_kind(ErrorKind::PermissionDenied));
97 assert!(!is_retryable_kind(ErrorKind::InvalidClientConfig));
98 assert!(!is_retryable_kind(ErrorKind::NoScriptError));
99 assert!(!is_retryable_kind(ErrorKind::Moved));
100 assert!(!is_retryable_kind(ErrorKind::Ask));
101 assert!(!is_retryable_kind(ErrorKind::ResponseError));
102 assert!(!is_retryable_kind(ErrorKind::ParseError));
103 assert!(!is_retryable_kind(ErrorKind::TypeError));
104 assert!(!is_retryable_kind(ErrorKind::ReadOnly));
105 }
106
107 #[test]
108 fn stable_str_for_common_kinds() {
109 assert_eq!(kind_to_stable_str(ErrorKind::IoError), "io_error");
110 assert_eq!(kind_to_stable_str(ErrorKind::FatalSendError), "fatal_send");
111 assert_eq!(kind_to_stable_str(ErrorKind::FatalReceiveError), "fatal_receive");
112 assert_eq!(kind_to_stable_str(ErrorKind::NoScriptError), "no_script");
113 assert_eq!(kind_to_stable_str(ErrorKind::AuthenticationFailed), "authentication_failed");
114 assert_eq!(kind_to_stable_str(ErrorKind::ClusterDown), "cluster_down");
115 assert_eq!(kind_to_stable_str(ErrorKind::Moved), "moved");
116 assert_eq!(kind_to_stable_str(ErrorKind::ReadOnly), "read_only");
117 }
118
119 #[test]
120 fn stable_str_is_snake_case_and_nonempty() {
121 use ferriskey::ErrorKind::*;
122 let all = [
123 ResponseError, ParseError, AuthenticationFailed, PermissionDenied,
124 TypeError, ExecAbortError, BusyLoadingError, NoScriptError,
125 InvalidClientConfig, Moved, Ask, TryAgain, ClusterDown, CrossSlot,
126 MasterDown, IoError, FatalSendError, FatalReceiveError, ClientError,
127 ExtensionError, ReadOnly,
128 ];
129 for k in all {
130 let s = kind_to_stable_str(k);
131 assert!(!s.is_empty(), "empty stable str for {k:?}");
132 assert!(
133 s.chars().all(|c| c.is_ascii_lowercase() || c == '_'),
134 "non snake_case stable str '{s}' for {k:?}"
135 );
136 }
137 }
138}