7 people like it.

Poor man's distributed actors

Knocked together a bare-minimum TCP wrapper for MailboxProcessor. Not intended for production.

  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
129: 
130: 
131: 
132: 
133: 
134: 
135: 
136: 
137: 
138: 
139: 
140: 
141: 
142: 
143: 
144: 
145: 
146: 
147: 
148: 
149: 
150: 
151: 
152: 
153: 
154: 
155: 
156: 
157: 
158: 
159: 
160: 
161: 
162: 
163: 
164: 
165: 
166: 
167: 
168: 
169: 
170: 
171: 
172: 
173: 
174: 
175: 
176: 
177: 
module Nessos.Vagrant.Tests.TcpActor

    // mini distributed actor implementation

    open System
    open System.Net
    open System.Net.Sockets
    open System.IO
    open System.Threading
    open System.Threading.Tasks

    open Microsoft.FSharp.Control

    open Nessos.FsPickler

    type AsyncBuilder with
        member __.Bind(f : Task<'T>, g : 'T -> Async<'S>) = __.Bind(Async.AwaitTask f, g)
        member __.Bind(f : Task, g : unit -> Async<'S>) = __.Bind(f.ContinueWith ignore, g)

    type Stream with
        member s.AsyncWriteBytes (bytes : byte []) =
            async {
                do! s.WriteAsync(BitConverter.GetBytes bytes.Length, 0, 4)
                do! s.WriteAsync(bytes, 0, bytes.Length)
                do! s.FlushAsync()
            }

        member s.AsyncReadBytes(length : int) =
            let rec readSegment buf offset remaining =
                async {
                    let! read = s.ReadAsync(buf, offset, remaining)
                    if read < remaining then
                        return! readSegment buf (offset + read) (remaining - read)
                    else
                        return ()
                }

            async {
                let bytes = Array.zeroCreate<byte> length
                do! readSegment bytes 0 length
                return bytes
            }

        member s.AsyncReadBytes() =
            async {
                let! lengthArr = s.AsyncReadBytes 4
                let length = BitConverter.ToInt32(lengthArr, 0)
                return! s.AsyncReadBytes length
            }

    // existentially pack reply channels

    type private IReplyChannelContainer<'T> =
        abstract PostWithReply : MailboxProcessor<'T> -> Async<obj>

    and private ReplyChannelContainer<'T, 'R>(msgB : AsyncReplyChannel<'R> -> 'T) =
        interface IReplyChannelContainer<'T> with
            member __.PostWithReply (mb : MailboxProcessor<'T>) = async {
                let! r = mb.PostAndAsyncReply msgB
                return r :> obj
            }

    type private ServerRequest<'T> =
        | Post of 'T
        | PostWithReply of IReplyChannelContainer<'T>

    and private ServerResponse =
        | Acknowledge
        | Reply of obj
        | Fault of exn

        
    type TcpActor<'T> (mailbox : MailboxProcessor<'T>, endpoint : IPEndPoint, ?pickler : FsPickler) =

        let pickler = match pickler with None -> new FsPickler() | Some p -> p
        let listener = new TcpListener(endpoint)

        let rec serverLoop () = async {
            try
                let! (client : TcpClient) = listener.AcceptTcpClientAsync()

                use client = client
                use stream = client.GetStream()

                let! (bytes : byte []) = stream.AsyncReadBytes()

                let! response = async {
                    try
                        let request = pickler.UnPickle<ServerRequest<'T>> bytes

                        match request with
                        | Post msg -> 
                            do mailbox.Post msg
                            return Acknowledge
                        | PostWithReply rcc ->
                            let! reply = rcc.PostWithReply mailbox
                            return Reply reply
                    with e -> return Fault e
                }

                let bytes = pickler.Pickle response
                do! stream.AsyncWriteBytes bytes

            with e -> printfn "Server error: %A" e

            return! serverLoop ()
        }

        let cts = new CancellationTokenSource()
        do 
            listener.Start()
            Async.Start(serverLoop (), cts.Token)

        member __.Stop () = cts.Cancel() ; listener.Stop()
        member __.MailboxProcessor = mailbox
        member __.GetTcpClient () = new TcpActorClient<'T>(endpoint, pickler)


    and TcpActorClient<'T>(serverEndpoint : IPEndPoint, ?pickler : FsPickler) =
        
        let pickler = match pickler with None -> new FsPickler() | Some p -> p

        let sendRequest (request : ServerRequest<'T>) = async {
            use client = new TcpClient()
            do! client.ConnectAsync(serverEndpoint.Address, serverEndpoint.Port)
            use stream = client.GetStream()

            let bytes = pickler.Pickle request
            do! stream.AsyncWriteBytes bytes
            let! (reply : byte []) = stream.AsyncReadBytes()

            return pickler.UnPickle<ServerResponse> reply
        }

        member __.PostAsync (msg : 'T) = async {
            let! response = sendRequest <| Post msg
            match response with
            | Acknowledge -> return ()
            | Reply o -> return failwithf "TcpActor: invalid response '%O'." o
            | Fault e -> return raise e
        }

        member __.PostAndReplyAsync (msgB : AsyncReplyChannel<'R> -> 'T) = async {
            let wrapper = new ReplyChannelContainer<'T,'R>(msgB)
            let! response = sendRequest <| PostWithReply wrapper
            match response with
            | Reply (:? 'R as r) -> return r
            | Reply o -> return failwithf "TcpActor: invalid response '%O'." o
            | Acknowledge -> return failwith "TcpActor: invalid response."
            | Fault e -> return raise e
        }

        member __.Post (msg : 'T) = __.PostAsync msg |> Async.RunSynchronously
        member __.PostAndReply (msgB) = __.PostAndReplyAsync msgB |> Async.RunSynchronously


    type TcpActor private () =

        static let parseEndpoint (endpoint : string) =
            let tokens = endpoint.Split(':')
            if tokens.Length <> 2 then raise <| new FormatException("invalid endpoint")
            let ipAddr = Dns.GetHostAddresses(tokens.[0]).[0]
            let port = int <| tokens.[1]
            new IPEndPoint(ipAddr, port)

        static member Create<'T>(behaviour : MailboxProcessor<'T> -> Async<unit>, ipEndPoint : IPEndPoint, ?pickler : FsPickler) =
            let mailbox = MailboxProcessor.Start behaviour
            new TcpActor<'T>(mailbox, ipEndPoint, ?pickler = pickler)

        static member Create<'T>(behaviour : MailboxProcessor<'T> -> Async<unit>, ipEndPoint : string, ?pickler : FsPickler) =
            TcpActor.Create(behaviour, parseEndpoint ipEndPoint, ?pickler = pickler)

        static member Connect<'T>(serverEndPoint : IPEndPoint, ?pickler : FsPickler) =
            new TcpActorClient<'T>(serverEndPoint, ?pickler = pickler)

        static member Connect<'T>(serverEndPoint : string, ?pickler : FsPickler) =
            new TcpActorClient<'T>(parseEndpoint serverEndPoint, ?pickler = pickler)
namespace Nessos
namespace Nessos.Vagrant
namespace Nessos.Vagrant.Tests
module TcpActor

from Nessos.Vagrant.Tests
namespace System
namespace System.Net
namespace System.Net.Sockets
namespace System.IO
namespace System.Threading
namespace System.Threading.Tasks
namespace Microsoft
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Control
namespace Nessos.FsPickler
type AsyncBuilder =
  private new : unit -> AsyncBuilder
  member Bind : computation:Async<'T> * binder:('T -> Async<'U>) -> Async<'U>
  member Combine : computation1:Async<unit> * computation2:Async<'T> -> Async<'T>
  member Delay : generator:(unit -> Async<'T>) -> Async<'T>
  member For : sequence:seq<'T> * body:('T -> Async<unit>) -> Async<unit>
  member Return : value:'T -> Async<'T>
  member ReturnFrom : computation:Async<'T> -> Async<'T>
  member TryFinally : computation:Async<'T> * compensation:(unit -> unit) -> Async<'T>
  member TryWith : computation:Async<'T> * catchHandler:(exn -> Async<'T>) -> Async<'T>
  member Using : resource:'T * binder:('T -> Async<'U>) -> Async<'U> (requires 'T :> IDisposable)
  ...

Full name: Microsoft.FSharp.Control.AsyncBuilder
member AsyncBuilder.Bind : f:Task<'T> * g:('T -> Async<'S>) -> Async<'S>

Full name: Nessos.Vagrant.Tests.TcpActor.Bind
val f : Task<'T>
Multiple items
type Task =
  new : action:Action -> Task + 7 overloads
  member AsyncState : obj
  member ContinueWith : continuationAction:Action<Task> -> Task + 9 overloads
  member CreationOptions : TaskCreationOptions
  member Dispose : unit -> unit
  member Exception : AggregateException
  member Id : int
  member IsCanceled : bool
  member IsCompleted : bool
  member IsFaulted : bool
  ...

Full name: System.Threading.Tasks.Task

--------------------
type Task<'TResult> =
  inherit Task
  new : function:Func<'TResult> -> Task<'TResult> + 7 overloads
  member ContinueWith : continuationAction:Action<Task<'TResult>> -> Task + 9 overloads
  member Result : 'TResult with get, set
  static member Factory : TaskFactory<'TResult>

Full name: System.Threading.Tasks.Task<_>

--------------------
Task(action: Action) : unit
Task(action: Action, cancellationToken: CancellationToken) : unit
Task(action: Action, creationOptions: TaskCreationOptions) : unit
Task(action: Action<obj>, state: obj) : unit
Task(action: Action, cancellationToken: CancellationToken, creationOptions: TaskCreationOptions) : unit
Task(action: Action<obj>, state: obj, cancellationToken: CancellationToken) : unit
Task(action: Action<obj>, state: obj, creationOptions: TaskCreationOptions) : unit
Task(action: Action<obj>, state: obj, cancellationToken: CancellationToken, creationOptions: TaskCreationOptions) : unit

--------------------
Task(function: Func<'TResult>) : unit
Task(function: Func<'TResult>, cancellationToken: CancellationToken) : unit
Task(function: Func<'TResult>, creationOptions: TaskCreationOptions) : unit
Task(function: Func<obj,'TResult>, state: obj) : unit
Task(function: Func<'TResult>, cancellationToken: CancellationToken, creationOptions: TaskCreationOptions) : unit
Task(function: Func<obj,'TResult>, state: obj, cancellationToken: CancellationToken) : unit
Task(function: Func<obj,'TResult>, state: obj, creationOptions: TaskCreationOptions) : unit
Task(function: Func<obj,'TResult>, state: obj, cancellationToken: CancellationToken, creationOptions: TaskCreationOptions) : unit
val g : ('T -> Async<'S>)
Multiple items
type Async
static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
static member AwaitTask : task:Task<'T> -> Async<'T>
static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
static member CancelDefaultToken : unit -> unit
static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
static member Ignore : computation:Async<'T> -> Async<unit>
static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
static member Sleep : millisecondsDueTime:int -> Async<unit>
static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T>
static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions -> Async<Task<'T>>
static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
static member SwitchToNewThread : unit -> Async<unit>
static member SwitchToThreadPool : unit -> Async<unit>
static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
static member CancellationToken : Async<CancellationToken>
static member DefaultCancellationToken : CancellationToken

Full name: Microsoft.FSharp.Control.Async

--------------------
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>
val __ : AsyncBuilder
member AsyncBuilder.Bind : f:Task * g:(unit -> Async<'S>) -> Async<'S>
member AsyncBuilder.Bind : f:Task<'T> * g:('T -> Async<'S>) -> Async<'S>
member AsyncBuilder.Bind : computation:Async<'T> * binder:('T -> Async<'U>) -> Async<'U>
static member Async.AwaitTask : task:Task<'T> -> Async<'T>
member AsyncBuilder.Bind : f:Task * g:(unit -> Async<'S>) -> Async<'S>

Full name: Nessos.Vagrant.Tests.TcpActor.Bind
val f : Task
val g : (unit -> Async<'S>)
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
Task.ContinueWith<'TResult>(continuationFunction: Func<Task,'TResult>) : Task<'TResult>
Task.ContinueWith(continuationAction: Action<Task>) : Task
Task.ContinueWith<'TResult>(continuationFunction: Func<Task,'TResult>, continuationOptions: TaskContinuationOptions) : Task<'TResult>
Task.ContinueWith<'TResult>(continuationFunction: Func<Task,'TResult>, scheduler: TaskScheduler) : Task<'TResult>
Task.ContinueWith<'TResult>(continuationFunction: Func<Task,'TResult>, cancellationToken: CancellationToken) : Task<'TResult>
Task.ContinueWith(continuationAction: Action<Task>, continuationOptions: TaskContinuationOptions) : Task
Task.ContinueWith(continuationAction: Action<Task>, scheduler: TaskScheduler) : Task
Task.ContinueWith(continuationAction: Action<Task>, cancellationToken: CancellationToken) : Task
Task.ContinueWith<'TResult>(continuationFunction: Func<Task,'TResult>, cancellationToken: CancellationToken, continuationOptions: TaskContinuationOptions, scheduler: TaskScheduler) : Task<'TResult>
Task.ContinueWith(continuationAction: Action<Task>, cancellationToken: CancellationToken, continuationOptions: TaskContinuationOptions, scheduler: TaskScheduler) : Task
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
type Stream =
  inherit MarshalByRefObject
  member BeginRead : buffer:byte[] * offset:int * count:int * callback:AsyncCallback * state:obj -> IAsyncResult
  member BeginWrite : buffer:byte[] * offset:int * count:int * callback:AsyncCallback * state:obj -> IAsyncResult
  member CanRead : bool
  member CanSeek : bool
  member CanTimeout : bool
  member CanWrite : bool
  member Close : unit -> unit
  member CopyTo : destination:Stream -> unit + 1 overload
  member Dispose : unit -> unit
  member EndRead : asyncResult:IAsyncResult -> int
  ...

Full name: System.IO.Stream
val s : Stream
member Stream.AsyncWriteBytes : bytes:byte [] -> Async<unit>

Full name: Nessos.Vagrant.Tests.TcpActor.AsyncWriteBytes
val bytes : byte []
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.byte

--------------------
type byte = Byte

Full name: Microsoft.FSharp.Core.byte
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
type BitConverter =
  static val IsLittleEndian : bool
  static member DoubleToInt64Bits : value:float -> int64
  static member GetBytes : value:bool -> byte[] + 9 overloads
  static member Int64BitsToDouble : value:int64 -> float
  static member ToBoolean : value:byte[] * startIndex:int -> bool
  static member ToChar : value:byte[] * startIndex:int -> char
  static member ToDouble : value:byte[] * startIndex:int -> float
  static member ToInt16 : value:byte[] * startIndex:int -> int16
  static member ToInt32 : value:byte[] * startIndex:int -> int
  static member ToInt64 : value:byte[] * startIndex:int -> int64
  ...

Full name: System.BitConverter
BitConverter.GetBytes(value: float) : byte []
BitConverter.GetBytes(value: float32) : byte []
BitConverter.GetBytes(value: uint64) : byte []
BitConverter.GetBytes(value: uint32) : byte []
BitConverter.GetBytes(value: uint16) : byte []
BitConverter.GetBytes(value: int64) : byte []
BitConverter.GetBytes(value: int) : byte []
BitConverter.GetBytes(value: int16) : byte []
BitConverter.GetBytes(value: char) : byte []
BitConverter.GetBytes(value: bool) : byte []
property Array.Length: int
member Stream.AsyncReadBytes : length:int -> Async<byte []>

Full name: Nessos.Vagrant.Tests.TcpActor.AsyncReadBytes
val length : int
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
val readSegment : ('a -> int -> int -> Async<unit>)
val buf : 'a
val offset : int
val remaining : int
val read : int
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
val zeroCreate : count:int -> 'T []

Full name: Microsoft.FSharp.Collections.Array.zeroCreate
member Stream.AsyncReadBytes : unit -> Async<byte []>

Full name: Nessos.Vagrant.Tests.TcpActor.AsyncReadBytes
val lengthArr : byte []
member Stream.AsyncReadBytes : unit -> Async<byte []>
member Stream.AsyncReadBytes : length:int -> Async<byte []>
BitConverter.ToInt32(value: byte [], startIndex: int) : int
type private IReplyChannelContainer<'T> =
  interface
    abstract member PostWithReply : MailboxProcessor<'T> -> Async<obj>
  end

Full name: Nessos.Vagrant.Tests.TcpActor.IReplyChannelContainer<_>
abstract member private IReplyChannelContainer.PostWithReply : MailboxProcessor<'T> -> Async<obj>

Full name: Nessos.Vagrant.Tests.TcpActor.IReplyChannelContainer`1.PostWithReply
Multiple items
type MailboxProcessor<'Msg> =
  interface IDisposable
  new : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:CancellationToken -> MailboxProcessor<'Msg>
  member Post : message:'Msg -> unit
  member PostAndAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply>
  member PostAndReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> 'Reply
  member PostAndTryAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply option>
  member Receive : ?timeout:int -> Async<'Msg>
  member Scan : scanner:('Msg -> Async<'T> option) * ?timeout:int -> Async<'T>
  member Start : unit -> unit
  member TryPostAndReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> 'Reply option
  ...

Full name: Microsoft.FSharp.Control.MailboxProcessor<_>

--------------------
new : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:CancellationToken -> MailboxProcessor<'Msg>
type obj = Object

Full name: Microsoft.FSharp.Core.obj
Multiple items
type private ReplyChannelContainer<'T,'R> =
  interface IReplyChannelContainer<'T>
  new : msgB:(AsyncReplyChannel<'R> -> 'T) -> ReplyChannelContainer<'T,'R>

Full name: Nessos.Vagrant.Tests.TcpActor.ReplyChannelContainer<_,_>

--------------------
private new : msgB:(AsyncReplyChannel<'R> -> 'T) -> ReplyChannelContainer<'T,'R>
val msgB : (AsyncReplyChannel<'R> -> 'T)
type AsyncReplyChannel<'Reply>
member Reply : value:'Reply -> unit

Full name: Microsoft.FSharp.Control.AsyncReplyChannel<_>
override private ReplyChannelContainer.PostWithReply : mb:MailboxProcessor<'T> -> Async<obj>

Full name: Nessos.Vagrant.Tests.TcpActor.ReplyChannelContainer`2.PostWithReply
val mb : MailboxProcessor<'T>
val r : 'R
member MailboxProcessor.PostAndAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply>
type private ServerRequest<'T> =
  | Post of 'T
  | PostWithReply of IReplyChannelContainer<'T>

Full name: Nessos.Vagrant.Tests.TcpActor.ServerRequest<_>
union case ServerRequest.Post: 'T -> ServerRequest<'T>
union case ServerRequest.PostWithReply: IReplyChannelContainer<'T> -> ServerRequest<'T>
type private ServerResponse =
  | Acknowledge
  | Reply of obj
  | Fault of exn

Full name: Nessos.Vagrant.Tests.TcpActor.ServerResponse
union case ServerResponse.Acknowledge: ServerResponse
union case ServerResponse.Reply: obj -> ServerResponse
union case ServerResponse.Fault: exn -> ServerResponse
type exn = Exception

Full name: Microsoft.FSharp.Core.exn
Multiple items
type TcpActor<'T> =
  new : mailbox:MailboxProcessor<'T> * endpoint:IPEndPoint * ?pickler:FsPickler -> TcpActor<'T>
  member GetTcpClient : unit -> TcpActorClient<'T>
  member Stop : unit -> unit
  member MailboxProcessor : MailboxProcessor<'T>

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActor<_>

--------------------
new : mailbox:MailboxProcessor<'T> * endpoint:IPEndPoint * ?pickler:FsPickler -> TcpActor<'T>
val mailbox : MailboxProcessor<'T>
val endpoint : IPEndPoint
Multiple items
type IPEndPoint =
  inherit EndPoint
  new : address:int64 * port:int -> IPEndPoint + 1 overload
  member Address : IPAddress with get, set
  member AddressFamily : AddressFamily
  member Create : socketAddress:SocketAddress -> EndPoint
  member Equals : comparand:obj -> bool
  member GetHashCode : unit -> int
  member Port : int with get, set
  member Serialize : unit -> SocketAddress
  member ToString : unit -> string
  static val MinPort : int
  ...

Full name: System.Net.IPEndPoint

--------------------
IPEndPoint(address: int64, port: int) : unit
IPEndPoint(address: IPAddress, port: int) : unit
val pickler : FsPickler option
type FsPickler =
  private new : unit -> FsPickler
  static member Clone : value:'T * ?pickler:Pickler<'T> * ?streamingContext:StreamingContext -> 'T
  static member ComputeHash : value:'T * ?hashFactory:IHashStreamFactory -> HashResult
  static member ComputeSize : value:'T * ?pickler:Pickler<'T> -> int64
  static member CreateBinarySerializer : ?forceLittleEndian:bool * ?typeConverter:ITypeNameConverter -> BinarySerializer
  static member CreateObjectSizeCounter : ?encoding:Encoding * ?resetInterval:int64 -> ObjectSizeCounter
  static member CreateXmlSerializer : ?typeConverter:ITypeNameConverter * ?indent:bool -> XmlSerializer
  static member DeclareSerializable : unit -> unit
  static member DeclareSerializable : t:Type -> unit
  static member EnsureSerializable : graph:'T * ?failOnCloneableOnlyTypes:bool -> unit
  ...

Full name: Nessos.FsPickler.FsPickler
val pickler : FsPickler
union case Option.None: Option<'T>
union case Option.Some: Value: 'T -> Option<'T>
val p : FsPickler
val listener : TcpListener
Multiple items
type TcpListener =
  new : localEP:IPEndPoint -> TcpListener + 2 overloads
  member AcceptSocket : unit -> Socket
  member AcceptTcpClient : unit -> TcpClient
  member AllowNatTraversal : allowed:bool -> unit
  member BeginAcceptSocket : callback:AsyncCallback * state:obj -> IAsyncResult
  member BeginAcceptTcpClient : callback:AsyncCallback * state:obj -> IAsyncResult
  member EndAcceptSocket : asyncResult:IAsyncResult -> Socket
  member EndAcceptTcpClient : asyncResult:IAsyncResult -> TcpClient
  member ExclusiveAddressUse : bool with get, set
  member LocalEndpoint : EndPoint
  ...

Full name: System.Net.Sockets.TcpListener

--------------------
TcpListener(localEP: IPEndPoint) : unit
TcpListener(localaddr: IPAddress, port: int) : unit
val serverLoop : (unit -> Async<'a>)
val client : TcpClient
Multiple items
type TcpClient =
  new : unit -> TcpClient + 3 overloads
  member Available : int
  member BeginConnect : host:string * port:int * requestCallback:AsyncCallback * state:obj -> IAsyncResult + 2 overloads
  member Client : Socket with get, set
  member Close : unit -> unit
  member Connect : remoteEP:IPEndPoint -> unit + 3 overloads
  member Connected : bool
  member EndConnect : asyncResult:IAsyncResult -> unit
  member ExclusiveAddressUse : bool with get, set
  member GetStream : unit -> NetworkStream
  ...

Full name: System.Net.Sockets.TcpClient

--------------------
TcpClient() : unit
TcpClient(localEP: IPEndPoint) : unit
TcpClient(family: AddressFamily) : unit
TcpClient(hostname: string, port: int) : unit
val stream : NetworkStream
TcpClient.GetStream() : NetworkStream
val response : ServerResponse
val request : ServerRequest<'T>
val msg : 'T
member MailboxProcessor.Post : message:'Msg -> unit
val rcc : IReplyChannelContainer<'T>
val reply : obj
abstract member private IReplyChannelContainer.PostWithReply : MailboxProcessor<'T> -> Async<obj>
val e : exn
Multiple items
type Pickle<'T> =
  new : bytes:byte [] -> Pickle<'T>
  val mutable private bytes: byte []
  member Bytes : byte []

Full name: Nessos.FsPickler.ExtensionMethods.Pickle<_>

--------------------
new : bytes:byte [] -> Pickle<'T>
member Stream.AsyncWriteBytes : bytes:byte [] -> Async<unit>
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val cts : CancellationTokenSource
Multiple items
type CancellationTokenSource =
  new : unit -> CancellationTokenSource
  member Cancel : unit -> unit + 1 overload
  member Dispose : unit -> unit
  member IsCancellationRequested : bool
  member Token : CancellationToken
  static member CreateLinkedTokenSource : [<ParamArray>] tokens:CancellationToken[] -> CancellationTokenSource + 1 overload

Full name: System.Threading.CancellationTokenSource

--------------------
CancellationTokenSource() : unit
TcpListener.Start() : unit
TcpListener.Start(backlog: int) : unit
static member Async.Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
property CancellationTokenSource.Token: CancellationToken
member TcpActor.Stop : unit -> unit

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActor`1.Stop
CancellationTokenSource.Cancel() : unit
CancellationTokenSource.Cancel(throwOnFirstException: bool) : unit
TcpListener.Stop() : unit
val __ : TcpActor<'T>
Multiple items
member TcpActor.MailboxProcessor : MailboxProcessor<'T>

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActor`1.MailboxProcessor

--------------------
type MailboxProcessor<'Msg> =
  interface IDisposable
  new : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:CancellationToken -> MailboxProcessor<'Msg>
  member Post : message:'Msg -> unit
  member PostAndAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply>
  member PostAndReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> 'Reply
  member PostAndTryAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply option>
  member Receive : ?timeout:int -> Async<'Msg>
  member Scan : scanner:('Msg -> Async<'T> option) * ?timeout:int -> Async<'T>
  member Start : unit -> unit
  member TryPostAndReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> 'Reply option
  ...

Full name: Microsoft.FSharp.Control.MailboxProcessor<_>

--------------------
new : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:CancellationToken -> MailboxProcessor<'Msg>
member TcpActor.GetTcpClient : unit -> TcpActorClient<'T>

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActor`1.GetTcpClient
Multiple items
type TcpActorClient<'T> =
  new : serverEndpoint:IPEndPoint * ?pickler:FsPickler -> TcpActorClient<'T>
  member Post : msg:'T -> unit
  member PostAndReply : msgB:(AsyncReplyChannel<'a> -> 'T) -> 'a
  member PostAndReplyAsync : msgB:(AsyncReplyChannel<'R> -> 'T) -> Async<'R>
  member PostAsync : msg:'T -> Async<unit>

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActorClient<_>

--------------------
new : serverEndpoint:IPEndPoint * ?pickler:FsPickler -> TcpActorClient<'T>
val serverEndpoint : IPEndPoint
val sendRequest : (ServerRequest<'T> -> Async<'a>)
property IPEndPoint.Address: IPAddress
property IPEndPoint.Port: int
val reply : byte []
member TcpActorClient.PostAsync : msg:'T -> Async<unit>

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActorClient`1.PostAsync
val o : obj
val failwithf : format:Printf.StringFormat<'T,'Result> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.failwithf
val raise : exn:Exception -> 'T

Full name: Microsoft.FSharp.Core.Operators.raise
val __ : TcpActorClient<'T>
member TcpActorClient.PostAndReplyAsync : msgB:(AsyncReplyChannel<'R> -> 'T) -> Async<'R>

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActorClient`1.PostAndReplyAsync
val wrapper : ReplyChannelContainer<'T,'R>
val failwith : message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.failwith
member TcpActorClient.Post : msg:'T -> unit

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActorClient`1.Post
member TcpActorClient.PostAsync : msg:'T -> Async<unit>
static member Async.RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
member TcpActorClient.PostAndReply : msgB:(AsyncReplyChannel<'a> -> 'T) -> 'a

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActorClient`1.PostAndReply
val msgB : (AsyncReplyChannel<'a> -> 'T)
member TcpActorClient.PostAndReplyAsync : msgB:(AsyncReplyChannel<'R> -> 'T) -> Async<'R>
Multiple items
type TcpActor =
  private new : unit -> TcpActor
  static member Connect : serverEndPoint:IPEndPoint * ?pickler:FsPickler -> TcpActorClient<'T>
  static member Connect : serverEndPoint:string * ?pickler:FsPickler -> TcpActorClient<'T>
  static member Create : behaviour:(MailboxProcessor<'T> -> Async<unit>) * ipEndPoint:IPEndPoint * ?pickler:FsPickler -> TcpActor<'T>
  static member Create : behaviour:(MailboxProcessor<'T> -> Async<unit>) * ipEndPoint:string * ?pickler:FsPickler -> TcpActor<'T>

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActor

--------------------
type TcpActor<'T> =
  new : mailbox:MailboxProcessor<'T> * endpoint:IPEndPoint * ?pickler:FsPickler -> TcpActor<'T>
  member GetTcpClient : unit -> TcpActorClient<'T>
  member Stop : unit -> unit
  member MailboxProcessor : MailboxProcessor<'T>

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActor<_>

--------------------
private new : unit -> TcpActor

--------------------
new : mailbox:MailboxProcessor<'T> * endpoint:IPEndPoint * ?pickler:FsPickler -> TcpActor<'T>
val parseEndpoint : (string -> IPEndPoint)
val endpoint : string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
val tokens : string []
String.Split([<ParamArray>] separator: char []) : string []
String.Split(separator: string [], options: StringSplitOptions) : string []
String.Split(separator: char [], options: StringSplitOptions) : string []
String.Split(separator: char [], count: int) : string []
String.Split(separator: string [], count: int, options: StringSplitOptions) : string []
String.Split(separator: char [], count: int, options: StringSplitOptions) : string []
Multiple items
type FormatException =
  inherit SystemException
  new : unit -> FormatException + 2 overloads

Full name: System.FormatException

--------------------
FormatException() : unit
FormatException(message: string) : unit
FormatException(message: string, innerException: exn) : unit
val ipAddr : IPAddress
type Dns =
  static member BeginGetHostAddresses : hostNameOrAddress:string * requestCallback:AsyncCallback * state:obj -> IAsyncResult
  static member BeginGetHostByName : hostName:string * requestCallback:AsyncCallback * stateObject:obj -> IAsyncResult
  static member BeginGetHostEntry : hostNameOrAddress:string * requestCallback:AsyncCallback * stateObject:obj -> IAsyncResult + 1 overload
  static member BeginResolve : hostName:string * requestCallback:AsyncCallback * stateObject:obj -> IAsyncResult
  static member EndGetHostAddresses : asyncResult:IAsyncResult -> IPAddress[]
  static member EndGetHostByName : asyncResult:IAsyncResult -> IPHostEntry
  static member EndGetHostEntry : asyncResult:IAsyncResult -> IPHostEntry
  static member EndResolve : asyncResult:IAsyncResult -> IPHostEntry
  static member GetHostAddresses : hostNameOrAddress:string -> IPAddress[]
  static member GetHostByAddress : address:string -> IPHostEntry + 1 overload
  ...

Full name: System.Net.Dns
Dns.GetHostAddresses(hostNameOrAddress: string) : IPAddress []
val port : int
static member TcpActor.Create : behaviour:(MailboxProcessor<'T> -> Async<unit>) * ipEndPoint:IPEndPoint * ?pickler:FsPickler -> TcpActor<'T>

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActor.Create
val behaviour : (MailboxProcessor<'T> -> Async<unit>)
val ipEndPoint : IPEndPoint
static member MailboxProcessor.Start : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:CancellationToken -> MailboxProcessor<'Msg>
static member TcpActor.Create : behaviour:(MailboxProcessor<'T> -> Async<unit>) * ipEndPoint:string * ?pickler:FsPickler -> TcpActor<'T>

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActor.Create
val ipEndPoint : string
static member TcpActor.Create : behaviour:(MailboxProcessor<'T> -> Async<unit>) * ipEndPoint:IPEndPoint * ?pickler:FsPickler -> TcpActor<'T>
static member TcpActor.Create : behaviour:(MailboxProcessor<'T> -> Async<unit>) * ipEndPoint:string * ?pickler:FsPickler -> TcpActor<'T>
static member TcpActor.Connect : serverEndPoint:IPEndPoint * ?pickler:FsPickler -> TcpActorClient<'T>

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActor.Connect
val serverEndPoint : IPEndPoint
static member TcpActor.Connect : serverEndPoint:string * ?pickler:FsPickler -> TcpActorClient<'T>

Full name: Nessos.Vagrant.Tests.TcpActor.TcpActor.Connect
val serverEndPoint : string

More information

Link:http://fssnip.net/mo
Posted:10 years ago
Author:Eirik Tsarpalis
Tags: actors