3 people like it.

Generic command/request agent with error handling

Generic command/request agent with error handling used to serialise posted commands and requests which are defined by closures. Useful in serialising communications to an instrument with a C API.

  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: 
178: 
179: 
180: 
181: 
182: 
183: 
184: 
185: 
186: 
187: 
188: 
189: 
190: 
191: 
192: 
193: 
194: 
195: 
196: 
197: 
198: 
199: 
200: 
201: 
202: 
203: 
204: 
205: 
206: 
207: 
208: 
209: 
210: 
211: 
212: 
213: 
214: 
215: 
216: 
217: 
218: 
219: 
220: 
221: 
222: 
223: 
224: 
225: 
226: 
227: 
228: 
#r @"..\packages\ExtCore.0.8.45\lib\net45\ExtCore.dll"
#r @"..\packages\log4net.2.0.3\lib\net40-full\log4net.dll"

open System
open ExtCore.Control
open log4net

[<AutoOpen>]
module CommandRequestAgent = 
    type Agent<'T> = MailboxProcessor<'T>

    [<AutoOpen>]
    module Model =
        /// Agent message, defining a command or request. Each command or request may fail, so the
        /// return type of the contained closures is of Choice<'Result, 'Error> where the error 
        /// message is a string. Commands do not return a vale in the success case, so the result
        /// type is unit. Requests can either return a value type or an object type. Command and
        /// request messages also include a description which is used for logging. Finally, the
        /// close message notifies the agent that it should stop processing messages.
        type internal CommandRequestMessage = 
            | Command       of description : string * commandFunc : (unit -> Choice<unit,      string>) * replyChannel : AsyncReplyChannel<Choice<unit,      string>>
            | ValueRequest  of description : string * requestFunc : (unit -> Choice<ValueType, string>) * replyChannel : AsyncReplyChannel<Choice<ValueType, string>>
            | ObjectRequest of description : string * requestFunc : (unit -> Choice<obj,       string>) * replyChannel : AsyncReplyChannel<Choice<obj,       string>>
            | Close         of                        closeFunc   : (unit -> Choice<unit,      string>) * replyChannel : AsyncReplyChannel<Choice<unit,      string>>
    
        /// A command/request agent processes messages of CommandRequestMessage type. The details
        /// of the implementation are hidden from the user of the library.
        type CommandRequestAgent = internal CommandRequestAgent of Agent<CommandRequestMessage>
    

    [<RequireQualifiedAccess>]
    /// Generic command/request agent with error handling used to serialise posted commands and
    /// requests which are defined by closures. Useful in serialising communications to an
    /// instrument with a C API.
    module CommandRequestAgent =

        /// Returns a string describing the message.
        let private messageDescription = function
            | Command       (description, _, _) 
            | ValueRequest  (description, _, _)
            | ObjectRequest (description, _, _) -> description
            | Close _                           -> "Close"

        /// Starts a new command/request agent with the given name (used for logging purposes) and 
        /// start-up function. The start-up function may fail, in which case the agent goes into a 
        /// failed state, returning failure results to future commands and requests. Furthermore,
        /// the processing of any given message may fail, in which case the agent will immediately
        /// enter the failed state and return failure to all future messages if it is set to persist
        /// failure.
        let create (name : string) persistFailure startupFunc = 
            CommandRequestAgent
            <| Agent.Start(fun (mailbox : Agent<CommandRequestMessage>) ->
                let log = LogManager.GetLogger name // create a logger
                
                let logResponse description = function
                    | Choice1Of2 s -> sprintf "Successfully responded to message \"%s\" with %A." description s |> log.Debug
                    | Choice2Of2 f -> sprintf "Failed to respond to message \"%s\" due to error: %A." description f |> log.Error
            
                /// Workflow performed when shutting down the agent.
                let closeAgent closeFunc (replyChannel : AsyncReplyChannel<Choice<unit, string>>) = async {
                    "Closing agent." |> log.Info

                    // perform the closing function and respond accordingly
                    let response =
                        match closeFunc () with
                        | Choice2Of2 f ->
                            Choice2Of2 <| sprintf "Failed to close agent due to error: %s" f
                        | Choice1Of2 () when mailbox.CurrentQueueLength <> 0 ->
                            Choice2Of2 <| sprintf "Closing agent with %d messages remaining in mailbox queue." mailbox.CurrentQueueLength 
                        | Choice1Of2 () -> Choice1Of2 ()

                    response |> replyChannel.Reply
                    logResponse "Close" response }
            
                /// Message-processing loop which replies to future messages with failure after an
                /// error has occured. The provided error description is used in the description of
                /// the failure when performing commands and requests and for logging.
                let rec failed error = async {
                    let! message = mailbox.Receive()
                    let errorMessage = sprintf "Received message \"%s\" after agent failed due to error: %s" (messageDescription message) error
                
                    match message with
                    | Command (_, _, replyChannel) ->
                        let response = Choice2Of2 errorMessage
                        response |> replyChannel.Reply
                        logResponse (messageDescription message) response
                        return! failed error
                
                    | ValueRequest (_, _, replyChannel) ->
                        let response = Choice2Of2 errorMessage
                        response |> replyChannel.Reply
                        logResponse (messageDescription message) response
                        return! failed error

                    | ObjectRequest (_, _, replyChannel) ->
                        let response = Choice2Of2 errorMessage
                        response |> replyChannel.Reply
                        logResponse (messageDescription message) response
                        return! failed error
                
                    | Close (closeFunc, replyChannel) -> 
                        // shutting down the agent is the only valid message in this state
                        do! closeAgent closeFunc replyChannel }

                /// Default message-processing loop.
                let rec loop () = async {
                    let! message = mailbox.Receive()
                    sprintf "Received message: %s." (messageDescription message) |> log.Debug
                
                    // continues the workflow after a message is processed, either remaining in the
                    // default loop or entering the failed loop depending on the result
                    let continueAfter response = async { 
                        match response with
                        | Choice2Of2 f when persistFailure -> return! failed f
                        | _                                -> return! loop () }

                    match message with 
                    | Command (_, commandFunc, replyChannel) ->
                        let response = commandFunc ()
                        response |> replyChannel.Reply
                        logResponse (messageDescription message) response
                        return! continueAfter response

                    | ValueRequest (_, requestFunc, replyChannel) ->
                        let response = requestFunc ()
                        response |> replyChannel.Reply
                        logResponse (messageDescription message) response
                        return! continueAfter response

                    | ObjectRequest (_, requestFunc, replyChannel) ->
                        let response = requestFunc ()
                        response |> replyChannel.Reply
                        logResponse (messageDescription message) response
                        return! continueAfter response
            
                    | Close (closeFunc, replyChannel) ->
                        // stop looping once the close message is received
                        do! closeAgent closeFunc replyChannel }
            
                async { 
                    // perform start-up
                    match startupFunc () with
                    | Choice1Of2 () -> do! loop () // enter the default loop if start-up is successful
                    | Choice2Of2 f  -> 
                        // enter the failure loop otherwise
                        let error = sprintf "Failed to start agent due to error: %s" f
                        do! failed error } )

        /// Posts a command to the message queue which will be executed by calling the provided
        /// function. The command may succeed or fail, which will be reflected in the asynchronous
        /// reply. All future messages will automatically result in failure if the command fails
        /// and the agent is set to persist failure. The supplied description is used for logging.
        let performCommand description commandFunc (CommandRequestAgent agent) =
            agent.PostAndAsyncReply (fun replyChannel -> Command(description, commandFunc, replyChannel))

        /// Posts a request to the message queue which will be executed by calling the provided
        /// function. The request may succeed or fail, which will be reflected in the asynchronous
        /// reply. If the request is successful, it returns an object type. All future messages will
        /// automatically result in failure if the command fails and the agent is set to persist
        /// failure. The supplied description is used for logging.
        let performObjectRequest<'Result when 'Result :> obj> description (requestFunc : unit -> Choice<'Result, string>) (CommandRequestAgent agent) = async {
            let castRequestFunc = requestFunc >> Choice.map (fun s -> s :> obj)
            let! response = agent.PostAndAsyncReply (fun replyChannel -> ObjectRequest(description, castRequestFunc, replyChannel))
            return response |> Choice.map (fun s -> s :?> 'Result) }
    
        /// Posts a request to the message queue which will be executed by calling the provided
        /// function. The request may succeed or fail, which will be reflected in the asynchronous
        /// reply. If the request is successful, it returns a value type. All future messages will
        /// automatically result in failure if the command fails and the agent is set to persist
        /// failure. The supplied description is used for logging.    
        let performValueRequest<'Result when 'Result :> ValueType> description (requestFunc : unit -> Choice<'Result, string>) (CommandRequestAgent agent) = async {
            let castRequestFunc = requestFunc >> Choice.map (fun s -> s :> ValueType)
            let! response = agent.PostAndAsyncReply (fun replyChannel ->ValueRequest(description, castRequestFunc, replyChannel))
            return response |> Choice.map (fun s -> s :?> 'Result) }

        /// Shuts down the message-processing agent after calling the supplied closing function. The
        /// function may succeed or fail, which will determine the asynchronously-returned result.
        /// Furthermore, the result will be failure if there are any remaining messages in the queue
        /// after this point.
        let close closeFunc (CommandRequestAgent agent) =
            agent.PostAndAsyncReply (fun replyChannel -> Close(closeFunc, replyChannel))

open ExtCore.Control
open log4net.Config

BasicConfigurator.Configure()

module DemoAgent =
    type DemoAgent = private DemoAgent of agent : CommandRequestAgent 

    let private divideImpl x y () = 
        if y = 0 then Choice2Of2 "Division by zero." else Choice1Of2 (x / y)
    
    let private firstElementImpl str () = 
        if String.length str = 0 
        then Choice2Of2 "Empty string." 
        else Choice1Of2 (String.sub str 0 1 |> String.ofSubstring)
    
    let private printPositiveNumberImp x () = 
        if x > 0 then 
            printfn "%d" x
            Choice1Of2 ()
        else
            Choice2Of2 "Negative number."

    let create () = 
        DemoAgent <| CommandRequestAgent.create "Demo" true (fun () -> printfn "Starting demo agent..." ; Choice1Of2 ())
    
    let divide x y (DemoAgent agent) =
        CommandRequestAgent.performValueRequest (sprintf "Divide %d by %d" x y) (divideImpl x y) agent

    let firstElement str (DemoAgent agent) =
        CommandRequestAgent.performObjectRequest (sprintf "Get first element of \"%s\"" str) (firstElementImpl str) agent

    let printPositiveNumber x (DemoAgent agent) =
        CommandRequestAgent.performCommand (sprintf "Printing positive number: %d" x) (printPositiveNumberImp x) agent

    let close (DemoAgent agent) =
        CommandRequestAgent.close (fun () -> printfn "Shutting down demo agent..." ; Choice1Of2 ()) agent


let demo = DemoAgent.create ()
let successfulValueRequest = DemoAgent.divide 4 2 demo |> Async.RunSynchronously
let successfulObjectRequest = DemoAgent.firstElement "43154" demo |> Async.RunSynchronously
let successfulCommand = DemoAgent.printPositiveNumber 53 demo |> Async.RunSynchronously
let failedValueRequest = DemoAgent.divide 5 0 demo |> Async.RunSynchronously
let failedObjectRequest = DemoAgent.firstElement "ABC" demo |> Async.RunSynchronously
let successfulShutdown = DemoAgent.close demo |> Async.RunSynchronously
namespace System
namespace ExtCore
namespace ExtCore.Control
namespace log4net
Multiple items
type AutoOpenAttribute =
  inherit Attribute
  new : unit -> AutoOpenAttribute
  new : path:string -> AutoOpenAttribute
  member Path : string

Full name: Microsoft.FSharp.Core.AutoOpenAttribute

--------------------
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
type Agent<'T> = MailboxProcessor<'T>

Full name: Script.CommandRequestAgent.Agent<_>
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:Threading.CancellationToken -> MailboxProcessor<'Msg>
type internal CommandRequestMessage =
  | Command of description: string * commandFunc: unit -> Choice<unit,string> * replyChannel: AsyncReplyChannel<Choice<unit,string>>
  | ValueRequest of description: string * requestFunc: unit -> Choice<ValueType,string> * replyChannel: AsyncReplyChannel<Choice<ValueType,string>>
  | ObjectRequest of description: string * requestFunc: unit -> Choice<obj,string> * replyChannel: AsyncReplyChannel<Choice<obj,string>>
  | Close of closeFunc: unit -> Choice<unit,string> * replyChannel: AsyncReplyChannel<Choice<unit,string>>

Full name: Script.CommandRequestAgent.Model.CommandRequestMessage


 Agent message, defining a command or request. Each command or request may fail, so the
 return type of the contained closures is of Choice<'Result, 'Error> where the error
 message is a string. Commands do not return a vale in the success case, so the result
 type is unit. Requests can either return a value type or an object type. Command and
 request messages also include a description which is used for logging. Finally, the
 close message notifies the agent that it should stop processing messages.
union case CommandRequestMessage.Command: description: string * commandFunc: unit -> Choice<unit,string> * replyChannel: AsyncReplyChannel<Choice<unit,string>> -> CommandRequestMessage
Multiple items
val string : value:'T -> string

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

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

Full name: Microsoft.FSharp.Core.string

--------------------
type string<'Measure> = string

Full name: ExtCore.string<_>
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
Multiple items
module Choice

from ExtCore

--------------------
type Choice<'T1,'T2> =
  | Choice1Of2 of 'T1
  | Choice2Of2 of 'T2

Full name: Microsoft.FSharp.Core.Choice<_,_>

--------------------
type Choice<'T1,'T2,'T3> =
  | Choice1Of3 of 'T1
  | Choice2Of3 of 'T2
  | Choice3Of3 of 'T3

Full name: Microsoft.FSharp.Core.Choice<_,_,_>

--------------------
type Choice<'T1,'T2,'T3,'T4> =
  | Choice1Of4 of 'T1
  | Choice2Of4 of 'T2
  | Choice3Of4 of 'T3
  | Choice4Of4 of 'T4

Full name: Microsoft.FSharp.Core.Choice<_,_,_,_>

--------------------
type Choice<'T1,'T2,'T3,'T4,'T5> =
  | Choice1Of5 of 'T1
  | Choice2Of5 of 'T2
  | Choice3Of5 of 'T3
  | Choice4Of5 of 'T4
  | Choice5Of5 of 'T5

Full name: Microsoft.FSharp.Core.Choice<_,_,_,_,_>

--------------------
type Choice<'T1,'T2,'T3,'T4,'T5,'T6> =
  | Choice1Of6 of 'T1
  | Choice2Of6 of 'T2
  | Choice3Of6 of 'T3
  | Choice4Of6 of 'T4
  | Choice5Of6 of 'T5
  | Choice6Of6 of 'T6

Full name: Microsoft.FSharp.Core.Choice<_,_,_,_,_,_>

--------------------
type Choice<'T1,'T2,'T3,'T4,'T5,'T6,'T7> =
  | Choice1Of7 of 'T1
  | Choice2Of7 of 'T2
  | Choice3Of7 of 'T3
  | Choice4Of7 of 'T4
  | Choice5Of7 of 'T5
  | Choice6Of7 of 'T6
  | Choice7Of7 of 'T7

Full name: Microsoft.FSharp.Core.Choice<_,_,_,_,_,_,_>
type AsyncReplyChannel<'Reply>
member Reply : value:'Reply -> unit

Full name: Microsoft.FSharp.Control.AsyncReplyChannel<_>
union case CommandRequestMessage.ValueRequest: description: string * requestFunc: unit -> Choice<ValueType,string> * replyChannel: AsyncReplyChannel<Choice<ValueType,string>> -> CommandRequestMessage
type ValueType =
  member Equals : obj:obj -> bool
  member GetHashCode : unit -> int
  member ToString : unit -> string

Full name: System.ValueType
union case CommandRequestMessage.ObjectRequest: description: string * requestFunc: unit -> Choice<obj,string> * replyChannel: AsyncReplyChannel<Choice<obj,string>> -> CommandRequestMessage
type obj = Object

Full name: Microsoft.FSharp.Core.obj
union case CommandRequestMessage.Close: closeFunc: unit -> Choice<unit,string> * replyChannel: AsyncReplyChannel<Choice<unit,string>> -> CommandRequestMessage
Multiple items
union case CommandRequestAgent.CommandRequestAgent: Agent<CommandRequestMessage> -> CommandRequestAgent

--------------------
type CommandRequestAgent = internal | CommandRequestAgent of Agent<CommandRequestMessage>

Full name: Script.CommandRequestAgent.Model.CommandRequestAgent


 A command/request agent processes messages of CommandRequestMessage type. The details
 of the implementation are hidden from the user of the library.
Multiple items
type RequireQualifiedAccessAttribute =
  inherit Attribute
  new : unit -> RequireQualifiedAccessAttribute

Full name: Microsoft.FSharp.Core.RequireQualifiedAccessAttribute

--------------------
new : unit -> RequireQualifiedAccessAttribute
Multiple items
union case CommandRequestAgent.CommandRequestAgent: Agent<CommandRequestMessage> -> CommandRequestAgent

--------------------
module CommandRequestAgent

from Script.CommandRequestAgent


 Generic command/request agent with error handling used to serialise posted commands and
 requests which are defined by closures. Useful in serialising communications to an
 instrument with a C API.


--------------------
type CommandRequestAgent = internal | CommandRequestAgent of Agent<CommandRequestMessage>

Full name: Script.CommandRequestAgent.Model.CommandRequestAgent


 A command/request agent processes messages of CommandRequestMessage type. The details
 of the implementation are hidden from the user of the library.
val private messageDescription : _arg1:CommandRequestMessage -> string

Full name: Script.CommandRequestAgent.CommandRequestAgent.messageDescription


 Returns a string describing the message.
val description : string
val create : name:string -> persistFailure:bool -> startupFunc:(unit -> Choice<unit,string>) -> CommandRequestAgent

Full name: Script.CommandRequestAgent.CommandRequestAgent.create


 Starts a new command/request agent with the given name (used for logging purposes) and
 start-up function. The start-up function may fail, in which case the agent goes into a
 failed state, returning failure results to future commands and requests. Furthermore,
 the processing of any given message may fail, in which case the agent will immediately
 enter the failed state and return failure to all future messages if it is set to persist
 failure.
val name : string
val persistFailure : bool
val startupFunc : (unit -> Choice<unit,string>)
static member MailboxProcessor.Start : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:Threading.CancellationToken -> MailboxProcessor<'Msg>
val mailbox : MailboxProcessor<CommandRequestMessage>
val log : ILog
type LogManager =
  static member CreateDomain : repositoryType:Type -> ILoggerRepository + 3 overloads
  static member CreateRepository : repositoryType:Type -> ILoggerRepository + 3 overloads
  static member Exists : name:string -> ILog + 2 overloads
  static member GetAllRepositories : unit -> ILoggerRepository[]
  static member GetCurrentLoggers : unit -> ILog[] + 2 overloads
  static member GetLogger : name:string -> ILog + 5 overloads
  static member GetLoggerRepository : unit -> ILoggerRepository + 2 overloads
  static member GetRepository : unit -> ILoggerRepository + 2 overloads
  static member ResetConfiguration : unit -> unit + 2 overloads
  static member Shutdown : unit -> unit
  ...

Full name: log4net.LogManager
LogManager.GetLogger(type: Type) : ILog
LogManager.GetLogger(name: string) : ILog
LogManager.GetLogger(repositoryAssembly: Reflection.Assembly, type: Type) : ILog
LogManager.GetLogger(repository: string, type: Type) : ILog
LogManager.GetLogger(repositoryAssembly: Reflection.Assembly, name: string) : ILog
LogManager.GetLogger(repository: string, name: string) : ILog
val logResponse : (string -> Choice<'a,'b> -> unit)
union case Choice.Choice1Of2: 'T1 -> Choice<'T1,'T2>
val s : 'a
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
ILog.Debug(message: obj) : unit
ILog.Debug(message: obj, exception: exn) : unit
union case Choice.Choice2Of2: 'T2 -> Choice<'T1,'T2>
val f : 'b
ILog.Error(message: obj) : unit
ILog.Error(message: obj, exception: exn) : unit
val closeAgent : ((unit -> Choice<unit,string>) -> AsyncReplyChannel<Choice<unit,string>> -> Async<unit>)


 Workflow performed when shutting down the agent.
val closeFunc : (unit -> Choice<unit,string>)
val replyChannel : AsyncReplyChannel<Choice<unit,string>>
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
ILog.Info(message: obj) : unit
ILog.Info(message: obj, exception: exn) : unit
val response : Choice<unit,string>
val f : string
property MailboxProcessor.CurrentQueueLength: int
member AsyncReplyChannel.Reply : value:'Reply -> unit
val failed : (string -> Async<unit>)


 Message-processing loop which replies to future messages with failure after an
 error has occured. The provided error description is used in the description of
 the failure when performing commands and requests and for logging.
val error : string
val message : CommandRequestMessage
member MailboxProcessor.Receive : ?timeout:int -> Async<'Msg>
val errorMessage : string
val response : Choice<'a,string>
val replyChannel : AsyncReplyChannel<Choice<ValueType,string>>
val replyChannel : AsyncReplyChannel<Choice<obj,string>>
val loop : (unit -> Async<unit>)


 Default message-processing loop.
val continueAfter : (Choice<'a,string> -> Async<unit>)
val commandFunc : (unit -> Choice<unit,string>)
val requestFunc : (unit -> Choice<ValueType,string>)
val response : Choice<ValueType,string>
val requestFunc : (unit -> Choice<obj,string>)
val response : Choice<obj,string>
val performCommand : description:string -> commandFunc:(unit -> Choice<unit,string>) -> CommandRequestAgent -> Async<Choice<unit,string>>

Full name: Script.CommandRequestAgent.CommandRequestAgent.performCommand


 Posts a command to the message queue which will be executed by calling the provided
 function. The command may succeed or fail, which will be reflected in the asynchronous
 reply. All future messages will automatically result in failure if the command fails
 and the agent is set to persist failure. The supplied description is used for logging.
val agent : Agent<CommandRequestMessage>
val performObjectRequest : description:string -> requestFunc:(unit -> Choice<'Result,string>) -> CommandRequestAgent -> Async<Choice<'Result,string>>

Full name: Script.CommandRequestAgent.CommandRequestAgent.performObjectRequest


 Posts a request to the message queue which will be executed by calling the provided
 function. The request may succeed or fail, which will be reflected in the asynchronous
 reply. If the request is successful, it returns an object type. All future messages will
 automatically result in failure if the command fails and the agent is set to persist
 failure. The supplied description is used for logging.
val requestFunc : (unit -> Choice<'Result,string>)
val castRequestFunc : (unit -> Choice<obj,string>)
val map : mapping:('T -> 'U) -> value:Choice<'T,'Error> -> Choice<'U,'Error>

Full name: ExtCore.Choice.map
val s : 'Result
member MailboxProcessor.PostAndAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply>
val s : obj
val performValueRequest : description:string -> requestFunc:(unit -> Choice<'Result,string>) -> CommandRequestAgent -> Async<Choice<'Result,string>> (requires 'Result :> ValueType)

Full name: Script.CommandRequestAgent.CommandRequestAgent.performValueRequest


 Posts a request to the message queue which will be executed by calling the provided
 function. The request may succeed or fail, which will be reflected in the asynchronous
 reply. If the request is successful, it returns a value type. All future messages will
 automatically result in failure if the command fails and the agent is set to persist
 failure. The supplied description is used for logging.
val requestFunc : (unit -> Choice<#ValueType,string>)
val castRequestFunc : (unit -> Choice<ValueType,string>)
val s : #ValueType
val s : ValueType
val close : closeFunc:(unit -> Choice<unit,string>) -> CommandRequestAgent -> Async<Choice<unit,string>>

Full name: Script.CommandRequestAgent.CommandRequestAgent.close


 Shuts down the message-processing agent after calling the supplied closing function. The
 function may succeed or fail, which will determine the asynchronously-returned result.
 Furthermore, the result will be failure if there are any remaining messages in the queue
 after this point.
namespace log4net.Config
type BasicConfigurator =
  static member Configure : unit -> ICollection + 5 overloads

Full name: log4net.Config.BasicConfigurator
BasicConfigurator.Configure() : Collections.ICollection
BasicConfigurator.Configure(repository: Repository.ILoggerRepository) : Collections.ICollection
BasicConfigurator.Configure([<ParamArray>] appenders: Appender.IAppender []) : Collections.ICollection
BasicConfigurator.Configure(appender: Appender.IAppender) : Collections.ICollection
BasicConfigurator.Configure(repository: Repository.ILoggerRepository, [<ParamArray>] appenders: Appender.IAppender []) : Collections.ICollection
BasicConfigurator.Configure(repository: Repository.ILoggerRepository, appender: Appender.IAppender) : Collections.ICollection
Multiple items
union case DemoAgent.DemoAgent: agent: CommandRequestAgent -> DemoAgent

--------------------
type DemoAgent = private | DemoAgent of agent: CommandRequestAgent

Full name: Script.DemoAgent.DemoAgent
Multiple items
union case CommandRequestAgent.CommandRequestAgent: Agent<CommandRequestMessage> -> CommandRequestAgent

--------------------
module CommandRequestAgent

from Script.CommandRequestAgent


 Generic command/request agent with error handling used to serialise posted commands and
 requests which are defined by closures. Useful in serialising communications to an
 instrument with a C API.


--------------------
module CommandRequestAgent

from Script

--------------------
type CommandRequestAgent = internal | CommandRequestAgent of Agent<CommandRequestMessage>

Full name: Script.CommandRequestAgent.Model.CommandRequestAgent


 A command/request agent processes messages of CommandRequestMessage type. The details
 of the implementation are hidden from the user of the library.
val private divideImpl : x:int -> y:int -> unit -> Choice<int,string>

Full name: Script.DemoAgent.divideImpl
val x : int
val y : int
val private firstElementImpl : str:string -> unit -> Choice<string,string>

Full name: Script.DemoAgent.firstElementImpl
val str : string
Multiple items
type String =
  new : value:char -> string + 7 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 2 overloads
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  member GetHashCode : unit -> int
  ...

Full name: System.String

--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : unit
val length : str:string -> int

Full name: Microsoft.FSharp.Core.String.length
val sub : str:string -> offset:int -> count:int -> substring

Full name: ExtCore.String.sub
val ofSubstring : substr:substring -> string

Full name: ExtCore.String.ofSubstring
val private printPositiveNumberImp : x:int -> unit -> Choice<unit,string>

Full name: Script.DemoAgent.printPositiveNumberImp
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val create : unit -> DemoAgent

Full name: Script.DemoAgent.create
val divide : x:int -> y:int -> DemoAgent -> Async<Choice<int,string>>

Full name: Script.DemoAgent.divide
val agent : CommandRequestAgent
val firstElement : str:string -> DemoAgent -> Async<Choice<string,string>>

Full name: Script.DemoAgent.firstElement
val printPositiveNumber : x:int -> DemoAgent -> Async<Choice<unit,string>>

Full name: Script.DemoAgent.printPositiveNumber
val close : DemoAgent -> Async<Choice<unit,string>>

Full name: Script.DemoAgent.close
val demo : DemoAgent.DemoAgent

Full name: Script.demo
module DemoAgent

from Script
val create : unit -> DemoAgent.DemoAgent

Full name: Script.DemoAgent.create
val successfulValueRequest : Choice<int,string>

Full name: Script.successfulValueRequest
val divide : x:int -> y:int -> DemoAgent.DemoAgent -> Async<Choice<int,string>>

Full name: Script.DemoAgent.divide
Multiple items
module Async

from ExtCore.Control

--------------------
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<_>
static member Async.RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:Threading.CancellationToken -> 'T
val successfulObjectRequest : Choice<string,string>

Full name: Script.successfulObjectRequest
val firstElement : str:string -> DemoAgent.DemoAgent -> Async<Choice<string,string>>

Full name: Script.DemoAgent.firstElement
val successfulCommand : Choice<unit,string>

Full name: Script.successfulCommand
val printPositiveNumber : x:int -> DemoAgent.DemoAgent -> Async<Choice<unit,string>>

Full name: Script.DemoAgent.printPositiveNumber
val failedValueRequest : Choice<int,string>

Full name: Script.failedValueRequest
val failedObjectRequest : Choice<string,string>

Full name: Script.failedObjectRequest
val successfulShutdown : Choice<unit,string>

Full name: Script.successfulShutdown
val close : DemoAgent.DemoAgent -> Async<Choice<unit,string>>

Full name: Script.DemoAgent.close
Raw view Test code New version

More information

Link:http://fssnip.net/rX
Posted:9 years ago
Author:Anton Tcholakov
Tags: async , mailboxprocessor