Created
July 8, 2019 12:03
-
-
Save vshapenko/d146504cedc5571c9f5092e13221c2bd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
} | |
let inline sendRequest< ^a,^b | |
when ^a:(static member encode: ^a -> seq<byte>) | |
and ^b:(static member decode: Seg -> ^b)> (request:^a) (filteredIds: int seq) (callbackFn:MessageData-> ^b) = | |
let rec send payload evt callback=async{ | |
Channel.sendEncrypted payload | |
let! res=evt | |
let! result=res |> Async.map callback | |
match result with | |
|Ok res-> | |
trace "send ok" | |
return res | |
|Error e-> | |
trace "resending" | |
return! send payload evt callback | |
} | |
let inline onCallback (msg:MessageData) :Result<Result< ^b,RpcError>,Error> = | |
trace <| sprintf "Invoked callback on %x" msg.TypeId | |
let typeId=msg.TypeId | |
match typeId with | |
| x when x=BadServerSalt.constructor -> trace <| sprintf "Received bad server salt,should resend" | |
Result.Error (Error.BadServerSalt ) | |
| x when x=RpcError.constructor -> let error:RpcError=deserialize msg.RawData | |
trace <| sprintf "error code=%i message='%s'" error.ErrorCode error.ErrorMessage | |
if(error.ErrorCode=48) | |
then | |
trace <| sprintf "Received bad server salt,should resend" | |
Result.Error (Error.BadServerSalt) | |
else | |
Ok(Result.Error error) | |
| x when filteredIds|>Seq.contains x -> Result.Ok(Ok (callbackFn msg)) | |
| x->trace <| sprintf "Unknown match %x" x | |
Ok(Result.Error {ErrorCode=1000;ErrorMessage="Unknown match"}) | |
async { | |
let filteredTypes = [ | |
yield BadServerSalt.constructor | |
yield! filteredIds | |
] | |
let dataToSend=serialize request|>wrap | |
trace <| sprintf "Sending request %A with message id %A and payload '%s'" request dataToSend.Id (dataToSend.Data |> Core.printArray) | |
let evt=filter filteredTypes | |
|> Event.filter(fun msg-> | |
trace <| sprintf "filtering event: messageId=%A rpcRequestId=%A" dataToSend.Id msg.RpcRequestId | |
match msg.RpcRequestId with | |
|None->true | |
|Some _-> msg.RpcRequestId= dataToSend.Id | |
); | |
let asyncEvt = evt |> Async.AwaitEvent |> Async.StartChild | |
let! res=send dataToSend asyncEvt onCallback | |
return res | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment