Skip to content

Instantly share code, notes, and snippets.

@vshapenko
Created July 8, 2019 12:03
Show Gist options
  • Save vshapenko/d146504cedc5571c9f5092e13221c2bd to your computer and use it in GitHub Desktop.
Save vshapenko/d146504cedc5571c9f5092e13221c2bd to your computer and use it in GitHub Desktop.
}
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