Browse Source

support custom error ty of dart event code gen

appflowy 3 years ago
parent
commit
222f6c7ba7

+ 1 - 1
app_flowy/macos/Podfile.lock

@@ -43,4 +43,4 @@ SPEC CHECKSUMS:
 
 PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
 
-COCOAPODS: 1.9.3
+COCOAPODS: 1.10.1

+ 23 - 33
app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart

@@ -5,13 +5,13 @@ part of 'dispatch.dart';
 class UserEventGetStatus {
     UserEventGetStatus();
 
-    Future<Either<UserDetail, FlowyError>> send() {
+    Future<Either<UserDetail, UserError>> send() {
      final request = FFIRequest.create()
         ..event = UserEvent.GetStatus.toString();
 
      return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold(
-        (bytes) => left(UserDetail.fromBuffer(bytes)),
-        (error) => right(error),
+        (okBytes) => left(UserDetail.fromBuffer(okBytes)),
+        (errBytes) => right(UserError.fromBuffer(errBytes)),
       ));
     }
 }
@@ -20,21 +20,16 @@ class UserEventSignIn {
      SignInRequest request;
      UserEventSignIn(this.request);
 
-    Future<Either<UserDetail, FlowyError>> send() {
-     return requestToBytes(request).fold(
-         (bytes) {
-            final request = FFIRequest.create()
-             ..event = UserEvent.SignIn.toString()
-             ..payload = bytes;
+    Future<Either<UserDetail, UserError>> send() {
+    final request = FFIRequest.create()
+          ..event = UserEvent.SignIn.toString()
+          ..payload = requestToBytes(this.request);
 
-           return Dispatch.asyncRequest(request)
-               .then((bytesResult) => bytesResult.fold(
-                 (bytes) => left(UserDetail.fromBuffer(bytes)),
-                 (error) => right(error),
-               ));
-         },
-         (err) => Future(() => right(err)),
-       );
+    return Dispatch.asyncRequest(request)
+        .then((bytesResult) => bytesResult.fold(
+          (okBytes) => left(UserDetail.fromBuffer(okBytes)),
+          (errBytes) => right(UserError.fromBuffer(errBytes)),
+        ));
     }
 }
 
@@ -42,34 +37,29 @@ class UserEventSignUp {
      SignUpRequest request;
      UserEventSignUp(this.request);
 
-    Future<Either<UserDetail, FlowyError>> send() {
-     return requestToBytes(request).fold(
-         (bytes) {
-            final request = FFIRequest.create()
-             ..event = UserEvent.SignUp.toString()
-             ..payload = bytes;
+    Future<Either<UserDetail, UserError>> send() {
+    final request = FFIRequest.create()
+          ..event = UserEvent.SignUp.toString()
+          ..payload = requestToBytes(this.request);
 
-           return Dispatch.asyncRequest(request)
-               .then((bytesResult) => bytesResult.fold(
-                 (bytes) => left(UserDetail.fromBuffer(bytes)),
-                 (error) => right(error),
-               ));
-         },
-         (err) => Future(() => right(err)),
-       );
+    return Dispatch.asyncRequest(request)
+        .then((bytesResult) => bytesResult.fold(
+          (okBytes) => left(UserDetail.fromBuffer(okBytes)),
+          (errBytes) => right(UserError.fromBuffer(errBytes)),
+        ));
     }
 }
 
 class UserEventSignOut {
     UserEventSignOut();
 
-    Future<Either<Uint8List, FlowyError>> send() {
+    Future<Either<Uint8List, UserError>> send() {
      final request = FFIRequest.create()
         ..event = UserEvent.SignOut.toString();
 
      return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold(
         (bytes) => left(bytes),
-        (error) => right(error),
+        (errBytes) => right(UserError.fromBuffer(errBytes)),
       ));
     }
 }

+ 26 - 17
app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart

@@ -1,5 +1,6 @@
 import 'dart:ffi';
 import 'package:dartz/dartz.dart';
+import 'package:flowy_logger/flowy_logger.dart';
 import 'package:flowy_sdk/protobuf/ffi_response.pb.dart';
 import 'package:isolates/isolates.dart';
 import 'package:isolates/ports.dart';
@@ -26,8 +27,7 @@ class DispatchException implements Exception {
 }
 
 class Dispatch {
-  static Future<Either<Uint8List, FlowyError>> asyncRequest(
-      FFIRequest request) {
+  static Future<Either<Uint8List, Uint8List>> asyncRequest(FFIRequest request) {
     // FFIRequest => Rust SDK
     final bytesFuture = _sendToRust(request);
 
@@ -41,12 +41,18 @@ class Dispatch {
   }
 }
 
-Future<Either<Uint8List, FlowyError>> _extractPayload(
+Future<Either<Uint8List, Uint8List>> _extractPayload(
     Future<Either<FFIResponse, FlowyError>> responseFuture) {
-  return responseFuture.then((response) {
-    return response.fold(
-      (l) => left(Uint8List.fromList(l.payload)),
-      (r) => right(r),
+  return responseFuture.then((result) {
+    return result.fold(
+      (response) {
+        if (response.code == FFIStatusCode.Ok) {
+          return left(Uint8List.fromList(response.payload));
+        } else {
+          return right(Uint8List.fromList(response.payload));
+        }
+      },
+      (error) => right(emptyBytes()),
     );
   });
 }
@@ -56,13 +62,11 @@ Future<Either<FFIResponse, FlowyError>> _extractResponse(
   return bytesFuture.future.then((bytes) {
     try {
       final response = FFIResponse.fromBuffer(bytes);
-      if (response.code != FFIStatusCode.Ok) {
-        return right(FlowyError.from(response));
-      }
-
       return left(response);
     } catch (e, s) {
-      return right(StackTraceError(e, s).toFlowyError());
+      final error = StackTraceError(e, s);
+      Log.error('Deserialize response failed. ${error.toString()}');
+      return right(error.asFlowyError());
     }
   });
 }
@@ -86,15 +90,20 @@ Completer<Uint8List> _sendToRust(FFIRequest request) {
   return completer;
 }
 
-Either<Uint8List, FlowyError> requestToBytes<T extends GeneratedMessage>(
-    T? message) {
+Uint8List requestToBytes<T extends GeneratedMessage>(T? message) {
   try {
     if (message != null) {
-      return left(message.writeToBuffer());
+      return message.writeToBuffer();
     } else {
-      return left(Uint8List.fromList([]));
+      return emptyBytes();
     }
   } catch (e, s) {
-    return right(FlowyError.fromError('${e.runtimeType}. Stack trace: $s'));
+    final error = StackTraceError(e, s);
+    Log.error('Serial request failed. ${error.toString()}');
+    return emptyBytes();
   }
 }
+
+Uint8List emptyBytes() {
+  return Uint8List.fromList([]);
+}

+ 8 - 16
app_flowy/packages/flowy_sdk/lib/dispatch/error.dart

@@ -1,5 +1,4 @@
-import 'package:flowy_logger/flowy_logger.dart';
-import 'package:flowy_sdk/protobuf/ffi_request.pb.dart';
+import 'package:flowy_sdk/protobuf/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/ffi_response.pb.dart';
 
 class FlowyError {
@@ -28,11 +27,13 @@ class FlowyError {
   }
 
   factory FlowyError.from(FFIResponse resp) {
-    return FlowyError(statusCode: resp.code, error: resp.error);
+    return FlowyError(statusCode: resp.code, error: "");
   }
 
-  factory FlowyError.fromError(String error) {
-    return FlowyError(statusCode: FFIStatusCode.Err, error: error);
+  UserError userErrorFromFlowyError() {
+    return UserError.create()
+      ..code = UserErrorCode.Unknown
+      ..msg = this.toString();
   }
 }
 
@@ -44,20 +45,11 @@ class StackTraceError {
     this.trace,
   );
 
-  FlowyError toFlowyError() {
-    Log.error('${error.runtimeType}\n');
-    Log.error('Stack trace \n $trace');
-    return FlowyError.fromError('${error.runtimeType}. Stack trace: $trace');
+  FlowyError asFlowyError() {
+    return FlowyError(statusCode: FFIStatusCode.Err, error: this.toString());
   }
 
   String toString() {
     return '${error.runtimeType}. Stack trace: $trace';
   }
 }
-
-FFIResponse error_response(FFIRequest request, StackTraceError error) {
-  var response = FFIResponse();
-  response.code = FFIStatusCode.Err;
-  response.error = error.toString();
-  return response;
-}

+ 1 - 2
app_flowy/packages/flowy_sdk/lib/flowy_sdk.dart

@@ -5,7 +5,6 @@ import 'dart:async';
 import 'package:dartz/dartz.dart';
 import 'package:flutter/services.dart';
 import 'dart:ffi';
-import 'dispatch/error.dart';
 import 'ffi/ffi.dart' as ffi;
 import 'package:ffi/ffi.dart';
 
@@ -31,7 +30,7 @@ class FlowySDK {
     final params = SignInRequest.create();
     params.email = "[email protected]";
     params.password = "Helloworld!2";
-    Either<UserDetail, FlowyError> resp = await UserEventSignIn(params).send();
+    Either<UserDetail, UserError> resp = await UserEventSignIn(params).send();
 
     resp.fold(
       (result) {

+ 5 - 19
app_flowy/packages/flowy_sdk/lib/protobuf/ffi_response.pb.dart

@@ -16,24 +16,19 @@ export 'ffi_response.pbenum.dart';
 class FFIResponse extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FFIResponse', createEmptyInstance: create)
     ..a<$core.List<$core.int>>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'payload', $pb.PbFieldType.OY)
-    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'error')
-    ..e<FFIStatusCode>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: FFIStatusCode.Unknown, valueOf: FFIStatusCode.valueOf, enumValues: FFIStatusCode.values)
+    ..e<FFIStatusCode>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: FFIStatusCode.Unknown, valueOf: FFIStatusCode.valueOf, enumValues: FFIStatusCode.values)
     ..hasRequiredFields = false
   ;
 
   FFIResponse._() : super();
   factory FFIResponse({
     $core.List<$core.int>? payload,
-    $core.String? error,
     FFIStatusCode? code,
   }) {
     final _result = create();
     if (payload != null) {
       _result.payload = payload;
     }
-    if (error != null) {
-      _result.error = error;
-    }
     if (code != null) {
       _result.code = code;
     }
@@ -70,21 +65,12 @@ class FFIResponse extends $pb.GeneratedMessage {
   void clearPayload() => clearField(1);
 
   @$pb.TagNumber(2)
-  $core.String get error => $_getSZ(1);
+  FFIStatusCode get code => $_getN(1);
   @$pb.TagNumber(2)
-  set error($core.String v) { $_setString(1, v); }
+  set code(FFIStatusCode v) { setField(2, v); }
   @$pb.TagNumber(2)
-  $core.bool hasError() => $_has(1);
+  $core.bool hasCode() => $_has(1);
   @$pb.TagNumber(2)
-  void clearError() => clearField(2);
-
-  @$pb.TagNumber(3)
-  FFIStatusCode get code => $_getN(2);
-  @$pb.TagNumber(3)
-  set code(FFIStatusCode v) { setField(3, v); }
-  @$pb.TagNumber(3)
-  $core.bool hasCode() => $_has(2);
-  @$pb.TagNumber(3)
-  void clearCode() => clearField(3);
+  void clearCode() => clearField(2);
 }
 

+ 1 - 2
app_flowy/packages/flowy_sdk/lib/protobuf/ffi_response.pbjson.dart

@@ -19,8 +19,7 @@ const FFIResponse$json = const {
   '1': 'FFIResponse',
   '2': const [
     const {'1': 'payload', '3': 1, '4': 1, '5': 12, '10': 'payload'},
-    const {'1': 'error', '3': 2, '4': 1, '5': 9, '10': 'error'},
-    const {'1': 'code', '3': 3, '4': 1, '5': 14, '6': '.FFIStatusCode', '10': 'code'},
+    const {'1': 'code', '3': 2, '4': 1, '5': 14, '6': '.FFIStatusCode', '10': 'code'},
   ],
 };
 

+ 1 - 13
rust-lib/dart-ffi/src/model/ffi_response.rs

@@ -18,9 +18,6 @@ pub struct FFIResponse {
     payload: Vec<u8>,
 
     #[pb(index = 2)]
-    error: String,
-
-    #[pb(index = 3)]
     code: FFIStatusCode,
 }
 
@@ -31,20 +28,11 @@ impl std::convert::From<EventResponse> for FFIResponse {
             Payload::None => vec![],
         };
 
-        let error = match resp.error {
-            Some(e) => format!("{}", e),
-            None => "".to_owned(),
-        };
-
         let code = match resp.status_code {
             StatusCode::Ok => FFIStatusCode::Ok,
             StatusCode::Err => FFIStatusCode::Err,
         };
 
-        FFIResponse {
-            payload,
-            error,
-            code,
-        }
+        FFIResponse { payload, code }
     }
 }

+ 23 - 68
rust-lib/dart-ffi/src/protobuf/model/ffi_response.rs

@@ -27,7 +27,6 @@
 pub struct FFIResponse {
     // message fields
     pub payload: ::std::vec::Vec<u8>,
-    pub error: ::std::string::String,
     pub code: FFIStatusCode,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
@@ -71,33 +70,7 @@ impl FFIResponse {
         ::std::mem::replace(&mut self.payload, ::std::vec::Vec::new())
     }
 
-    // string error = 2;
-
-
-    pub fn get_error(&self) -> &str {
-        &self.error
-    }
-    pub fn clear_error(&mut self) {
-        self.error.clear();
-    }
-
-    // Param is passed by value, moved
-    pub fn set_error(&mut self, v: ::std::string::String) {
-        self.error = v;
-    }
-
-    // Mutable pointer to the field.
-    // If field is not initialized, it is initialized with default value first.
-    pub fn mut_error(&mut self) -> &mut ::std::string::String {
-        &mut self.error
-    }
-
-    // Take field
-    pub fn take_error(&mut self) -> ::std::string::String {
-        ::std::mem::replace(&mut self.error, ::std::string::String::new())
-    }
-
-    // .FFIStatusCode code = 3;
+    // .FFIStatusCode code = 2;
 
 
     pub fn get_code(&self) -> FFIStatusCode {
@@ -126,10 +99,7 @@ impl ::protobuf::Message for FFIResponse {
                     ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.payload)?;
                 },
                 2 => {
-                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.error)?;
-                },
-                3 => {
-                    ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.code, 3, &mut self.unknown_fields)?
+                    ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.code, 2, &mut self.unknown_fields)?
                 },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@@ -146,11 +116,8 @@ impl ::protobuf::Message for FFIResponse {
         if !self.payload.is_empty() {
             my_size += ::protobuf::rt::bytes_size(1, &self.payload);
         }
-        if !self.error.is_empty() {
-            my_size += ::protobuf::rt::string_size(2, &self.error);
-        }
         if self.code != FFIStatusCode::Unknown {
-            my_size += ::protobuf::rt::enum_size(3, self.code);
+            my_size += ::protobuf::rt::enum_size(2, self.code);
         }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
@@ -161,11 +128,8 @@ impl ::protobuf::Message for FFIResponse {
         if !self.payload.is_empty() {
             os.write_bytes(1, &self.payload)?;
         }
-        if !self.error.is_empty() {
-            os.write_string(2, &self.error)?;
-        }
         if self.code != FFIStatusCode::Unknown {
-            os.write_enum(3, ::protobuf::ProtobufEnum::value(&self.code))?;
+            os.write_enum(2, ::protobuf::ProtobufEnum::value(&self.code))?;
         }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
@@ -210,11 +174,6 @@ impl ::protobuf::Message for FFIResponse {
                 |m: &FFIResponse| { &m.payload },
                 |m: &mut FFIResponse| { &mut m.payload },
             ));
-            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
-                "error",
-                |m: &FFIResponse| { &m.error },
-                |m: &mut FFIResponse| { &mut m.error },
-            ));
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<FFIStatusCode>>(
                 "code",
                 |m: &FFIResponse| { &m.code },
@@ -237,7 +196,6 @@ impl ::protobuf::Message for FFIResponse {
 impl ::protobuf::Clear for FFIResponse {
     fn clear(&mut self) {
         self.payload.clear();
-        self.error.clear();
         self.code = FFIStatusCode::Unknown;
         self.unknown_fields.clear();
     }
@@ -309,28 +267,25 @@ impl ::protobuf::reflect::ProtobufValue for FFIStatusCode {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x12ffi_response.proto\"a\n\x0bFFIResponse\x12\x18\n\x07payload\x18\
-    \x01\x20\x01(\x0cR\x07payload\x12\x14\n\x05error\x18\x02\x20\x01(\tR\x05\
-    error\x12\"\n\x04code\x18\x03\x20\x01(\x0e2\x0e.FFIStatusCodeR\x04code*-\
-    \n\rFFIStatusCode\x12\x0b\n\x07Unknown\x10\0\x12\x06\n\x02Ok\x10\x01\x12\
-    \x07\n\x03Err\x10\x02J\xe2\x02\n\x06\x12\x04\0\0\x0b\x01\n\x08\n\x01\x0c\
-    \x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x06\x01\n\n\n\x03\x04\0\
-    \x01\x12\x03\x02\x08\x13\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x16\n\
-    \x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\t\n\x0c\n\x05\x04\0\x02\0\x01\
-    \x12\x03\x03\n\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x14\x15\n\x0b\
-    \n\x04\x04\0\x02\x01\x12\x03\x04\x04\x15\n\x0c\n\x05\x04\0\x02\x01\x05\
-    \x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\x10\n\
-    \x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x13\x14\n\x0b\n\x04\x04\0\x02\
-    \x02\x12\x03\x05\x04\x1b\n\x0c\n\x05\x04\0\x02\x02\x06\x12\x03\x05\x04\
-    \x11\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\x12\x16\n\x0c\n\x05\x04\0\
-    \x02\x02\x03\x12\x03\x05\x19\x1a\n\n\n\x02\x05\0\x12\x04\x07\0\x0b\x01\n\
-    \n\n\x03\x05\0\x01\x12\x03\x07\x05\x12\n\x0b\n\x04\x05\0\x02\0\x12\x03\
-    \x08\x04\x10\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x08\x04\x0b\n\x0c\n\x05\
-    \x05\0\x02\0\x02\x12\x03\x08\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\t\
-    \x04\x0b\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\t\x04\x06\n\x0c\n\x05\x05\
-    \0\x02\x01\x02\x12\x03\t\t\n\n\x0b\n\x04\x05\0\x02\x02\x12\x03\n\x04\x0c\
-    \n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\n\x04\x07\n\x0c\n\x05\x05\0\x02\
-    \x02\x02\x12\x03\n\n\x0bb\x06proto3\
+    \n\x12ffi_response.proto\"K\n\x0bFFIResponse\x12\x18\n\x07payload\x18\
+    \x01\x20\x01(\x0cR\x07payload\x12\"\n\x04code\x18\x02\x20\x01(\x0e2\x0e.\
+    FFIStatusCodeR\x04code*-\n\rFFIStatusCode\x12\x0b\n\x07Unknown\x10\0\x12\
+    \x06\n\x02Ok\x10\x01\x12\x07\n\x03Err\x10\x02J\xab\x02\n\x06\x12\x04\0\0\
+    \n\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x05\
+    \x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x13\n\x0b\n\x04\x04\0\x02\0\x12\
+    \x03\x03\x04\x16\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\t\n\x0c\n\
+    \x05\x04\0\x02\0\x01\x12\x03\x03\n\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\
+    \x03\x03\x14\x15\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x1b\n\x0c\n\
+    \x05\x04\0\x02\x01\x06\x12\x03\x04\x04\x11\n\x0c\n\x05\x04\0\x02\x01\x01\
+    \x12\x03\x04\x12\x16\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x19\x1a\n\
+    \n\n\x02\x05\0\x12\x04\x06\0\n\x01\n\n\n\x03\x05\0\x01\x12\x03\x06\x05\
+    \x12\n\x0b\n\x04\x05\0\x02\0\x12\x03\x07\x04\x10\n\x0c\n\x05\x05\0\x02\0\
+    \x01\x12\x03\x07\x04\x0b\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x07\x0e\x0f\
+    \n\x0b\n\x04\x05\0\x02\x01\x12\x03\x08\x04\x0b\n\x0c\n\x05\x05\0\x02\x01\
+    \x01\x12\x03\x08\x04\x06\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x08\t\n\n\
+    \x0b\n\x04\x05\0\x02\x02\x12\x03\t\x04\x0c\n\x0c\n\x05\x05\0\x02\x02\x01\
+    \x12\x03\t\x04\x07\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\t\n\x0bb\x06pro\
+    to3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 1 - 2
rust-lib/dart-ffi/src/protobuf/proto/ffi_response.proto

@@ -2,8 +2,7 @@ syntax = "proto3";
 
 message FFIResponse {
     bytes payload = 1;
-    string error = 2;
-    FFIStatusCode code = 3;
+    FFIStatusCode code = 2;
 }
 enum FFIStatusCode {
     Unknown = 0;

+ 2 - 1
rust-lib/flowy-ast/src/attr.rs

@@ -5,7 +5,6 @@ use syn::{
     self,
     parse::{self, Parse},
     Meta::{List, NameValue, Path},
-    NestedMeta,
     NestedMeta::{Lit, Meta},
 };
 
@@ -300,6 +299,8 @@ impl ASTEnumAttrVariant {
     pub fn event_input(&self) -> Option<syn::Path> { self.event_attrs.input.clone() }
 
     pub fn event_output(&self) -> Option<syn::Path> { self.event_attrs.output.clone() }
+
+    pub fn event_error(&self) -> String { self.event_attrs.error_ty.as_ref().unwrap().clone() }
 }
 
 fn get_event_attrs_from(

+ 3 - 0
rust-lib/flowy-ast/src/event_ast.rs

@@ -6,6 +6,7 @@ pub struct EventASTContext {
     pub event_request_struct: syn::Ident,
     pub event_input: Option<syn::Path>,
     pub event_output: Option<syn::Path>,
+    pub event_error: String,
 }
 
 impl EventASTContext {
@@ -23,6 +24,7 @@ impl EventASTContext {
 
         let event_input = variant.event_input();
         let event_output = variant.event_output();
+        let event_error = variant.event_error();
 
         EventASTContext {
             event,
@@ -30,6 +32,7 @@ impl EventASTContext {
             event_request_struct,
             event_input,
             event_output,
+            event_error,
         }
     }
 }

+ 1 - 1
rust-lib/flowy-infra/src/kv/kv.rs

@@ -6,7 +6,7 @@ use flowy_sqlite::{DBConnection, Database, PoolConfig};
 use lazy_static::lazy_static;
 use std::{
     path::Path,
-    sync::{PoisonError, RwLock, RwLockWriteGuard},
+    sync::{RwLock, RwLockWriteGuard},
 };
 
 const DB_NAME: &str = "kv.db";

+ 1 - 1
rust-lib/flowy-test/src/lib.rs

@@ -1,7 +1,7 @@
 use flowy_dispatch::prelude::*;
 pub use flowy_sdk::*;
 use std::{
-    convert::{TryFrom, TryInto},
+    convert::TryFrom,
     fmt::{Debug, Display},
     fs,
     hash::Hash,

+ 1 - 1
rust-lib/flowy-user/src/errors.rs

@@ -1,6 +1,6 @@
 use derive_more::Display;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
-use flowy_dispatch::prelude::{DispatchError, EventResponse, ResponseBuilder};
+use flowy_dispatch::prelude::{EventResponse, ResponseBuilder};
 use std::convert::TryInto;
 
 #[derive(Debug, Default, Clone, ProtoBuf)]

+ 2 - 3
rust-lib/flowy-user/src/services/user_session/user_server.rs

@@ -3,7 +3,6 @@ use crate::{
     errors::{ErrorBuilder, UserError, UserErrorCode},
     sql_tables::User,
 };
-use std::sync::RwLock;
 
 pub trait UserServer {
     fn sign_up(&self, params: SignUpParams) -> Result<User, UserError>;
@@ -36,11 +35,11 @@ impl UserServer for MockUserServer {
         ))
     }
 
-    fn get_user_info(&self, user_id: &str) -> Result<UserDetail, UserError> {
+    fn get_user_info(&self, _user_id: &str) -> Result<UserDetail, UserError> {
         Err(ErrorBuilder::new(UserErrorCode::Unknown).build())
     }
 
-    fn sign_out(&self, user_id: &str) -> Result<(), UserError> {
+    fn sign_out(&self, _user_id: &str) -> Result<(), UserError> {
         Err(ErrorBuilder::new(UserErrorCode::Unknown).build())
     }
 }

+ 1 - 1
rust-lib/flowy-user/src/services/user_session/user_session.rs

@@ -9,7 +9,7 @@ use lazy_static::lazy_static;
 use std::sync::RwLock;
 
 use crate::{
-    entities::{SignInParams, SignUpParams, UserDetail, UserId},
+    entities::{SignInParams, SignUpParams, UserDetail},
     errors::{ErrorBuilder, UserError, UserErrorCode},
     services::user_session::{
         database::UserDB,

+ 3 - 2
scripts/flowy-tool/src/dart_event/dart_event.rs

@@ -74,13 +74,13 @@ pub fn parse_event_crate(event_crate: &DartEventCrate) -> Vec<EventASTContext> {
             let file_path = format!("{}/{}", event_crate.crate_path, event_file);
             let file_content = read_file(file_path.as_ref()).unwrap();
             let ast = syn::parse_file(file_content.as_ref()).expect("Unable to parse file");
-
             ast.items
                 .iter()
                 .map(|item| match item {
                     Item::Enum(item_enum) => {
                         let ctxt = Ctxt::new();
-                        let attrs = flowy_ast::enum_from_ast(&ctxt, &item_enum.variants);
+                        let attrs =
+                            flowy_ast::enum_from_ast(&ctxt, &item_enum.variants, &item_enum.attrs);
                         ctxt.check().unwrap();
                         attrs
                             .iter()
@@ -114,6 +114,7 @@ pub fn ast_to_event_render_ctx(ast: &Vec<EventASTContext>) -> Vec<EventRenderCon
             return EventRenderContext {
                 input_deserializer,
                 output_deserializer,
+                error_deserializer: event_ast.event_error.clone(),
                 event: event_ast.event.to_string(),
                 event_ty: event_ast.event_ty.to_string(),
             };

+ 4 - 0
scripts/flowy-tool/src/dart_event/event_template.rs

@@ -13,6 +13,7 @@ part of 'dispatch.dart';
 pub struct EventRenderContext {
     pub input_deserializer: Option<String>,
     pub output_deserializer: Option<String>,
+    pub error_deserializer: String,
     pub event: String,
     pub event_ty: String,
 }
@@ -50,6 +51,9 @@ impl EventTemplate {
             Some(ref output) => self.tera_context.insert("output_deserializer", output),
         }
 
+        self.tera_context
+            .insert("error_deserializer", &ctx.error_deserializer);
+
         let tera = get_tera("dart_event");
         match tera.render("event_template.tera", &self.tera_context) {
             Ok(r) => Some(r),

+ 12 - 16
scripts/flowy-tool/src/dart_event/event_template.tera

@@ -10,23 +10,19 @@ class {{ event_class }} {
     {{ event_class }}();
 {%- endif %}
 
-    Future<Either<{{ output_deserializer }}, FlowyError>> send() {
+    Future<Either<{{ output_deserializer }}, {{ error_deserializer }}>> send() {
 
 {%- if has_input  %}
-     return requestToBytes(request).fold(
-         (bytes) {
-            final request = FFIRequest.create()
-             ..event = {{ event }}.toString()
-             ..payload = bytes;
+    final request = FFIRequest.create()
+          ..event = {{ event }}.toString()
+          ..payload = requestToBytes(this.request);
+
+    return Dispatch.asyncRequest(request)
+        .then((bytesResult) => bytesResult.fold(
+          (okBytes) => left({{ output_deserializer }}.fromBuffer(okBytes)),
+          (errBytes) => right({{ error_deserializer }}.fromBuffer(errBytes)),
+        ));
 
-           return Dispatch.asyncRequest(request)
-               .then((bytesResult) => bytesResult.fold(
-                 (bytes) => left({{ output_deserializer }}.fromBuffer(bytes)),
-                 (error) => right(error),
-               ));
-         },
-         (err) => Future(() => right(err)),
-       );
 {%- else %}
      final request = FFIRequest.create()
         ..event = {{ event }}.toString();
@@ -36,11 +32,11 @@ class {{ event_class }} {
 
      return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold(
      {%- if has_output  %}
-        (bytes) => left({{ output_deserializer }}.fromBuffer(bytes)),
+        (okBytes) => left({{ output_deserializer }}.fromBuffer(okBytes)),
      {%- else %}
         (bytes) => left(bytes),
      {%- endif %}
-        (error) => right(error),
+        (errBytes) => right({{ error_deserializer }}.fromBuffer(errBytes)),
       ));
 {%- endif %}
     }

+ 2 - 1
scripts/flowy-tool/src/proto/ast.rs

@@ -129,13 +129,14 @@ pub fn get_ast_structs(ast: &syn::File) -> Vec<Struct> {
 pub fn get_ast_enums(ast: &syn::File) -> Vec<FlowyEnum> {
     let mut flowy_enums: Vec<FlowyEnum> = vec![];
     let ctxt = Ctxt::new();
+    let enum_attrs = &ast.attrs;
     ast.items.iter().for_each(|item| {
         // https://docs.rs/syn/1.0.54/syn/enum.Item.html
         match item {
             Item::Enum(item_enum) => {
                 flowy_enums.push(FlowyEnum {
                     name: item_enum.ident.to_string(),
-                    attrs: flowy_ast::enum_from_ast(&ctxt, &item_enum.variants),
+                    attrs: flowy_ast::enum_from_ast(&ctxt, &item_enum.variants, enum_attrs),
                 });
             }
             _ => {}