errors.rs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. use bytes::Bytes;
  2. use derive_more::Display;
  3. use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
  4. use flowy_dispatch::prelude::{EventResponse, ResponseBuilder};
  5. use flowy_document::errors::DocError;
  6. use flowy_net::errors::ErrorCode as ServerErrorCode;
  7. use std::{convert::TryInto, fmt, fmt::Debug};
  8. pub type WorkspaceResult<T> = std::result::Result<T, WorkspaceError>;
  9. #[derive(Debug, Default, Clone, ProtoBuf)]
  10. pub struct WorkspaceError {
  11. #[pb(index = 1)]
  12. pub code: ErrorCode,
  13. #[pb(index = 2)]
  14. pub msg: String,
  15. }
  16. macro_rules! static_workspace_error {
  17. ($name:ident, $status:expr) => {
  18. #[allow(non_snake_case, missing_docs)]
  19. pub fn $name() -> WorkspaceError {
  20. WorkspaceError {
  21. code: $status,
  22. msg: format!("{}", $status),
  23. }
  24. }
  25. };
  26. }
  27. impl WorkspaceError {
  28. pub fn new(code: ErrorCode, msg: &str) -> Self {
  29. Self {
  30. code,
  31. msg: msg.to_owned(),
  32. }
  33. }
  34. static_workspace_error!(workspace_name, ErrorCode::WorkspaceNameInvalid);
  35. static_workspace_error!(workspace_id, ErrorCode::WorkspaceIdInvalid);
  36. static_workspace_error!(color_style, ErrorCode::AppColorStyleInvalid);
  37. static_workspace_error!(workspace_desc, ErrorCode::WorkspaceDescInvalid);
  38. static_workspace_error!(app_name, ErrorCode::AppNameInvalid);
  39. static_workspace_error!(app_id, ErrorCode::AppIdInvalid);
  40. static_workspace_error!(view_name, ErrorCode::ViewNameInvalid);
  41. static_workspace_error!(view_thumbnail, ErrorCode::ViewThumbnailInvalid);
  42. static_workspace_error!(invalid_view_id, ErrorCode::ViewIdInvalid);
  43. static_workspace_error!(view_desc, ErrorCode::ViewDescInvalid);
  44. static_workspace_error!(view_data, ErrorCode::ViewDataInvalid);
  45. static_workspace_error!(unauthorized, ErrorCode::UserUnauthorized);
  46. static_workspace_error!(internal, ErrorCode::InternalError);
  47. static_workspace_error!(record_not_found, ErrorCode::RecordNotFound);
  48. static_workspace_error!(ws, ErrorCode::WsConnectError);
  49. pub fn context<T: Debug>(mut self, error: T) -> Self {
  50. self.msg = format!("{:?}", error);
  51. self
  52. }
  53. }
  54. #[derive(Debug, Clone, ProtoBuf_Enum, Display, PartialEq, Eq)]
  55. pub enum ErrorCode {
  56. #[display(fmt = "Workspace name is invalid")]
  57. WorkspaceNameInvalid = 0,
  58. #[display(fmt = "Workspace id is invalid")]
  59. WorkspaceIdInvalid = 1,
  60. #[display(fmt = "Color style of the App is invalid")]
  61. AppColorStyleInvalid = 2,
  62. #[display(fmt = "Workspace desc is invalid")]
  63. WorkspaceDescInvalid = 3,
  64. #[display(fmt = "Id of the App is invalid")]
  65. AppIdInvalid = 10,
  66. #[display(fmt = "Name of the App is invalid")]
  67. AppNameInvalid = 11,
  68. #[display(fmt = "Name of the View is invalid")]
  69. ViewNameInvalid = 20,
  70. #[display(fmt = "Thumbnail of the view is invalid")]
  71. ViewThumbnailInvalid = 21,
  72. #[display(fmt = "Id of the View is invalid")]
  73. ViewIdInvalid = 22,
  74. #[display(fmt = "Description of the View is invalid")]
  75. ViewDescInvalid = 23,
  76. #[display(fmt = "View data is invalid")]
  77. ViewDataInvalid = 24,
  78. #[display(fmt = "User unauthorized")]
  79. UserUnauthorized = 100,
  80. #[display(fmt = "Workspace websocket error")]
  81. WsConnectError = 200,
  82. #[display(fmt = "Server error")]
  83. InternalError = 1000,
  84. #[display(fmt = "Record not found")]
  85. RecordNotFound = 1001,
  86. }
  87. pub fn internal_error<T>(e: T) -> WorkspaceError
  88. where
  89. T: std::fmt::Debug,
  90. {
  91. WorkspaceError::internal().context(e)
  92. }
  93. impl std::default::Default for ErrorCode {
  94. fn default() -> Self { ErrorCode::InternalError }
  95. }
  96. impl std::convert::From<flowy_document::errors::DocError> for WorkspaceError {
  97. fn from(error: DocError) -> Self { WorkspaceError::internal().context(error) }
  98. }
  99. impl std::convert::From<flowy_net::errors::ServerError> for WorkspaceError {
  100. fn from(error: flowy_net::errors::ServerError) -> Self {
  101. let code = server_error_to_workspace_error(error.code);
  102. WorkspaceError::new(code, &error.msg)
  103. }
  104. }
  105. impl std::convert::From<flowy_database::Error> for WorkspaceError {
  106. fn from(error: flowy_database::Error) -> Self { WorkspaceError::internal().context(error) }
  107. }
  108. impl flowy_dispatch::Error for WorkspaceError {
  109. fn as_response(&self) -> EventResponse {
  110. let bytes: Bytes = self.clone().try_into().unwrap();
  111. ResponseBuilder::Err().data(bytes).build()
  112. }
  113. }
  114. impl fmt::Display for WorkspaceError {
  115. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}: {}", &self.code, &self.msg) }
  116. }
  117. fn server_error_to_workspace_error(code: ServerErrorCode) -> ErrorCode {
  118. match code {
  119. ServerErrorCode::UserUnauthorized => ErrorCode::UserUnauthorized,
  120. ServerErrorCode::RecordNotFound => ErrorCode::RecordNotFound,
  121. _ => ErrorCode::InternalError,
  122. }
  123. }