thrift

    基于 Xpeng/moonthrift 的有界多请求 RPC 会话

    Download zip
    Version
    0.7.0
    License
    MIT AND Apache-2.0
    Last updated
    5 hours ago
    Downloads
    4

    Dependencies

    #可执行 API 示例

    增加 Binary/Compact Map/Set,12 组 Apache Thrift 独立向量对照。这些例子调用公开 API,并随 moon test 执行。

    ///|
    test "documented map container" {
    let value = @thrift.MapValue(
    Some(@thrift.BinaryKind),
    Some(@thrift.I32Kind),
    [(@thrift.Binary(b"answer"), @thrift.I32(42))],
    )
    let wire = @thrift.encode(value, @thrift.BinaryProtocol)
    assert_eq(
    @thrift.decode(wire, @thrift.MapKind, @thrift.BinaryProtocol),
    value,
    )
    }

    另有 MoonBit IDL 解析、schema 校验和类型绑定生成,以及 Node TCP/TLS/mTLS 宿主,见 README.md。仍不声称完整 Apache Thrift 兼容;本例所用通用值 API 解码 Compact 空 Map 时,线路不含键值类型信息,类型字段为 None/None。

    #分帧 RPC 客户端

    ///|
    test "documented framed RPC exchange" {
    let client = @thrift.Client::new(@thrift.CompactProtocol)
    let request = client.call("ping", @thrift.Struct([]))
    let frames = @thrift.FrameDecoder::new()
    let message = @thrift.decode_message(
    frames.feed(request)[0],
    @thrift.CompactProtocol,
    )
    let reply : @thrift.Message = {
    name: message.name,
    sequence_id: message.sequence_id,
    message_type: 2,
    body: @thrift.Struct([(0, @thrift.I32(42))]),
    }
    assert_eq(
    client.feed(@thrift.encode_framed_message(reply, @thrift.CompactProtocol)),
    [reply],
    )
    client.finish()
    }

    CodecError

    pub(all) suberror CodecError {
    Invalid(String)
    } derive(
    Debug
    )

    SchemaError

    pub suberror SchemaError {
    Syntax(String, IdlLocation)
    InvalidSchema(String)
    } derive(
    Debug
    )

    Client

    pub struct Client {
    codec : MessageCodec
    decoder : FrameStream
    pending : Map[Int, String]
    next_sequence : UInt
    failed : Bool
    exhausted : Bool
    }

    Transport-independent framed RPC client state. The host supplies socket I/O. Protocol errors poison this instance; create a new client after reconnecting.

    Client::abort

    fn Client::abort(self : Client) -> Array[PendingCall]

    Seal the session and transfer its unresolved call identities to the host. This does not cancel work at the peer or make retry safe.

    Client::call

    fn Client::call(self : Client, name : String, body : Value, oneway? : Bool) -> Bytes raise CodecError

    Encode a request and register its signed sequence id. Oneway calls do not create a pending response. Returns one complete TFramedTransport frame.

    Client::call_with_id

    fn Client::call_with_id(self : Client, name : String, body : Value, oneway? : Bool, response_name? : String?) -> (Int, Bytes) raise CodecError

    Return the registered sequence id alongside the frame. Multiplexed requests may specify the unprefixed response name used by TMultiplexedProtocol peers.

    Client::feed

    fn Client::feed(self : Client, chunk : Bytes) -> Array[Message] raise CodecError

    Accept arbitrary socket chunks. Responses may arrive in any order. Application exceptions (type 3) are delivered as Message values.

    Client::finish

    fn Client::finish(self : Client) -> Unit raise CodecError

    Validate clean EOF, including outstanding calls.

    Client::new

    fn Client::new(protocol : Protocol, strict_read? : Bool, strict_write? : Bool, codec? : MessageCodec?, frame_stream? : FrameStream?) -> Client raise CodecError

    When supplied, codec owns wire format selection; protocol and strict flags apply only to the default builtin codec.

    Client::pending_calls

    fn Client::pending_calls(self : Client) -> Array[PendingCall]

    Snapshot of requests not delivered by feed. After failure their remote execution outcome is unknown; this list is not permission to retry.

    Client::pending_count

    fn Client::pending_count(self : Client) -> Int

    FrameDecoder

    pub struct FrameDecoder {
    max_frame : Int
    header : UInt64
    header_bytes : Int
    expected : Int
    buffer : Array[Byte]
    failed : Bool
    }

    A bounded incremental transport decoder. Invalid input poisons the decoder until reset. feed is transactional: no partial frames are returned on error.

    FrameDecoder::feed

    fn FrameDecoder::feed(self : FrameDecoder, chunk : Bytes) -> Array[Bytes] raise CodecError

    FrameDecoder::finish

    fn FrameDecoder::finish(self : FrameDecoder) -> Unit raise CodecError

    FrameDecoder::new

    fn FrameDecoder::new(max_frame? : Int) -> FrameDecoder raise CodecError

    FrameDecoder::reset

    fn FrameDecoder::reset(self : FrameDecoder) -> Unit

    FrameStream

    pub struct FrameStream {
    encoder : (Bytes) -> Bytes raise CodecError
    decoder : (Bytes) -> Array[Bytes] raise CodecError
    eof : () -> Unit raise CodecError
    closed : Bool
    failed : Bool
    }

    Stateful framing adapter. Use one instance per connection. A framing error seals this instance; EOF seals only input so a server may finish replies.

    FrameStream::builtin

    fn FrameStream::builtin() -> FrameStream raise CodecError

    FrameStream::encode

    fn FrameStream::encode(self : FrameStream, payload : Bytes) -> Bytes raise CodecError

    FrameStream::feed

    fn FrameStream::feed(self : FrameStream, chunk : Bytes) -> Array[Bytes] raise CodecError

    FrameStream::finish

    fn FrameStream::finish(self : FrameStream) -> Unit raise CodecError

    FrameStream::new

    fn FrameStream::new(encode~ : (Bytes) -> Bytes raise CodecError, feed~ : (Bytes) -> Array[Bytes] raise CodecError, finish~ : () -> Unit raise CodecError) -> FrameStream

    IdlConst

    pub(all) enum IdlConst {
    IntegerConstant(Int64)
    FloatConstant(Double)
    StringConstant(String)
    NameConstant(String)
    ListConstant(Array[IdlConst])
    MapConstant(Array[(IdlConst, IdlConst)])
    } derive(Eq,
    Debug
    )

    IdlConst::equal

    fn IdlConst::equal(IdlConst, IdlConst) -> Bool

    IdlConst::not_equal

    fn IdlConst::not_equal(x : IdlConst, y : IdlConst) -> Bool

    IdlConst::to_repr

    IdlDefinition

    pub(all) enum IdlDefinition {
    Alias(String, IdlType, Map[String, String])
    Enumeration(String, Array[(String, Int)], Map[String, String])
    Record(String, String, Array[IdlField], Map[String, String])
    Constant(String, IdlType, IdlConst)
    Service(String, String?, Array[IdlMethod], Map[String, String])
    } derive(Eq,
    Debug
    )

    IdlDefinition::equal

    IdlDefinition::not_equal

    fn IdlDefinition::not_equal(x : IdlDefinition, y : IdlDefinition) -> Bool

    IdlField

    pub(all) struct IdlField {
    id : Int
    name : String
    field_type : IdlType
    requiredness : String
    default_value : IdlConst?
    annotations : Map[String, String]
    location : IdlLocation
    } derive(Eq,
    Debug
    )

    IdlField::equal

    fn IdlField::equal(IdlField, IdlField) -> Bool

    IdlField::not_equal

    fn IdlField::not_equal(x : IdlField, y : IdlField) -> Bool

    IdlField::to_repr

    IdlLocation

    pub(all) struct IdlLocation {
    source : String
    offset : Int
    line : Int
    column : Int
    } derive(Eq, ToJson,
    Debug
    )

    IdlLocation::equal

    fn IdlLocation::equal(IdlLocation, IdlLocation) -> Bool

    IdlLocation::not_equal

    fn IdlLocation::not_equal(x : IdlLocation, y : IdlLocation) -> Bool

    IdlLocation::to_json

    fn IdlLocation::to_json(IdlLocation) -> Json

    IdlMethod

    pub(all) struct IdlMethod {
    name : String
    return_type : IdlType
    oneway : Bool
    arguments : Array[IdlField]
    exceptions : Array[IdlField]
    annotations : Map[String, String]
    location : IdlLocation
    } derive(Eq,
    Debug
    )

    IdlMethod::equal

    fn IdlMethod::equal(IdlMethod, IdlMethod) -> Bool

    IdlMethod::not_equal

    fn IdlMethod::not_equal(x : IdlMethod, y : IdlMethod) -> Bool

    IdlModule

    pub(all) struct IdlModule {
    source : String
    includes : Array[String]
    namespaces : Map[String, String]
    cpp_includes : Array[String]
    definitions : Array[IdlDefinition]
    } derive(Eq,
    Debug
    )

    IdlModule::equal

    fn IdlModule::equal(IdlModule, IdlModule) -> Bool

    IdlModule::not_equal

    fn IdlModule::not_equal(x : IdlModule, y : IdlModule) -> Bool

    IdlType

    pub(all) enum IdlType {
    Base(String)
    Named(String)
    ListOf(IdlType)
    SetOf(IdlType)
    MapOf(IdlType, IdlType)
    } derive(Eq,
    Debug
    )

    IdlType::equal

    fn IdlType::equal(IdlType, IdlType) -> Bool

    IdlType::not_equal

    fn IdlType::not_equal(x : IdlType, y : IdlType) -> Bool

    IdlType::to_repr

    Kind

    pub(all) enum Kind {
    BoolKind
    ByteKind
    I16Kind
    I32Kind
    I64Kind
    DoubleKind
    BinaryKind
    StructKind
    ListKind
    SetKind
    MapKind
    UuidKind
    } derive(Eq,
    Debug
    )

    Kind::equal

    fn Kind::equal(Kind, Kind) -> Bool

    Kind::not_equal

    fn Kind::not_equal(x : Kind, y : Kind) -> Bool

    Kind::to_repr

    Message

    pub(all) struct Message {
    name : String
    message_type : Int
    sequence_id : Int
    body : Value
    } derive(Eq,
    Debug
    )

    RPC message envelope. message_type: 1=call, 2=reply, 3=exception, 4=oneway.

    Message::equal

    fn Message::equal(Message, Message) -> Bool

    Message::not_equal

    fn Message::not_equal(x : Message, y : Message) -> Bool

    Message::to_repr

    MessageCodec

    pub struct MessageCodec {
    encoder : (Message) -> Bytes raise CodecError
    decoder : (Bytes) -> Message raise CodecError
    }

    Message serialization boundary. Framing, sequence correlation and socket lifetimes stay in the runtime, independently of the selected wire codec.

    MessageCodec::builtin

    fn MessageCodec::builtin(protocol : Protocol, strict_read? : Bool, strict_write? : Bool) -> MessageCodec

    MessageCodec::decode

    fn MessageCodec::decode(self : MessageCodec, data : Bytes) -> Message raise CodecError

    MessageCodec::encode

    fn MessageCodec::encode(self : MessageCodec, message : Message) -> Bytes raise CodecError

    MessageCodec::new

    fn MessageCodec::new(encode~ : (Message) -> Bytes raise CodecError, decode~ : (Bytes) -> Message raise CodecError) -> MessageCodec

    PendingCall

    pub struct PendingCall {
    sequence_id : Int
    response_name : String
    } derive(Eq,
    Debug
    )

    PendingCall::equal

    fn PendingCall::equal(PendingCall, PendingCall) -> Bool

    PendingCall::not_equal

    fn PendingCall::not_equal(x : PendingCall, y : PendingCall) -> Bool

    Protocol

    pub(all) enum Protocol {
    BinaryProtocol
    CompactProtocol
    } derive(Eq,
    Debug
    )

    Protocol::equal

    fn Protocol::equal(Protocol, Protocol) -> Bool

    Protocol::not_equal

    fn Protocol::not_equal(x : Protocol, y : Protocol) -> Bool

    Protocol::to_repr

    RpcOutcome

    pub(all) enum RpcOutcome {
    Success(Json)
    DeclaredException(String, Json)
    ApplicationFailure(Int, String)
    } derive(Eq,
    Debug
    )

    RpcOutcome::equal

    fn RpcOutcome::equal(RpcOutcome, RpcOutcome) -> Bool

    RpcOutcome::not_equal

    fn RpcOutcome::not_equal(x : RpcOutcome, y : RpcOutcome) -> Bool

    Schema

    pub struct Schema {
    // private fields
    }

    Resolved IDL modules. No filesystem access is performed by this value.

    Schema::decode_json

    fn Schema::decode_json(self : Schema, name : String, data : Bytes, protocol : Protocol) -> Json raise

    Schema::describe

    fn Schema::describe(self : Schema) -> Json raise SchemaError

    Canonical resolved schema description, retaining declarations and annotations.

    Schema::encode_json

    fn Schema::encode_json(self : Schema, name : String, input : Json, protocol : Protocol) -> Bytes raise

    Schema::from_json

    fn Schema::from_json(self : Schema, name : String, input : Json) -> Value raise SchemaError

    Convert named-field JSON to a wire tree, applying explicit IDL defaults. i64 uses decimal strings, binary uses {"$binary":"hex"}, and maps use pair arrays.

    Schema::get_method

    fn Schema::get_method(self : Schema, service : String, name : String) -> IdlMethod raise SchemaError

    Schema::get_module

    fn Schema::get_module(self : Schema) -> IdlModule

    Schema::make_call

    fn Schema::make_call(self : Schema, service : String, name : String, arguments : Json, sequence_id : Int) -> Message raise SchemaError

    Schema::make_reply

    fn Schema::make_reply(self : Schema, service : String, name : String, sequence_id : Int, outcome : RpcOutcome) -> Message raise SchemaError

    Schema::read_call

    fn Schema::read_call(self : Schema, service : String, request : Message) -> Json raise SchemaError

    Schema::read_reply

    fn Schema::read_reply(self : Schema, service : String, name : String, response : Message) -> RpcOutcome raise SchemaError

    Schema::service_functions

    fn Schema::service_functions(self : Schema, service : String) -> Array[IdlMethod] raise SchemaError

    Schema::services

    fn Schema::services(self : Schema) -> Array[String]

    Schema::to_json

    fn Schema::to_json(self : Schema, name : String, value : Value) -> Json raise SchemaError

    Read a wire tree with unknown/type-mismatched fields skipped and required fields checked.

    Schema::warnings

    fn Schema::warnings(self : Schema) -> Array[String]

    Value

    pub(all) enum Value {
    Bool(Bool)
    Byte(Int)
    I16(Int)
    I32(Int)
    I64(Int64)
    Double(Double)
    Binary(Bytes)
    Struct(Array[(Int, Value)])
    List(Kind, Array[Value])
    SetValue(Kind, Array[Value])
    MapValue(Kind?, Kind?, Array[(Value, Value)])
    Uuid(Bytes)
    } derive(Eq,
    Debug
    )

    Value::equal

    fn Value::equal(Value, Value) -> Bool

    Value::kind

    fn Value::kind(self : Value) -> Kind

    Value::not_equal

    fn Value::not_equal(x : Value, y : Value) -> Bool

    Value::to_repr

    application_exception

    fn application_exception(name : String, sequence_id : Int, code : Int, message : String) -> Message

    Construct standard TApplicationException without an IDL dependency.

    compile_schema

    fn compile_schema(root : String, sources : Map[String, String], include_paths? : Array[String]) -> Schema raise SchemaError

    Compile in-memory .thrift files, following includes relative to each source.

    decode

    fn decode(data : Bytes, root : Kind, protocol : Protocol) -> Value raise CodecError

    Root type is supplied by caller, as in Thrift IDL. Trailing bytes are rejected.

    decode_message

    fn decode_message(data : Bytes, protocol : Protocol, strict_read? : Bool) -> Message raise CodecError

    decode_prefix

    fn decode_prefix(data : Bytes, root : Kind, protocol : Protocol) -> (Value, Int) raise CodecError

    Read one value from a byte stream; returns the consumed byte count.

    decode_selected

    fn decode_selected(data : Bytes, fields : Array[(Int, Kind)], protocol : Protocol) -> Value raise CodecError

    Decode only requested fields of a struct. Unknown and mismatched fields are skipped on the wire. Duplicates retain wire order, as in the generic decoder.

    encode

    fn encode(value : Value, protocol : Protocol) -> Bytes raise CodecError

    encode_framed_message

    fn encode_framed_message(message : Message, protocol : Protocol, strict_write? : Bool) -> Bytes raise CodecError

    encode_message

    fn encode_message(message : Message, protocol : Protocol, strict_write? : Bool) -> Bytes raise CodecError

    Binary and Compact v1 envelopes. Binary writes strict headers by default.

    frame

    fn frame(payload : Bytes, max_frame? : Int) -> Bytes raise CodecError

    Apache TFramedTransport wire format: nonnegative signed big-endian i32 length.

    parse_idl

    fn parse_idl(text : String, source? : String) -> IdlModule raise SchemaError

    Parse one Thrift IDL document. Includes and named references are resolved by compile_schema.

    skip_prefix

    fn skip_prefix(data : Bytes, root : Kind, protocol : Protocol) -> Int raise CodecError

    Return the byte length of the first wire value, validating skipped data.