Skip to content

Instantly share code, notes, and snippets.

@louthy
Last active January 18, 2018 14:37
Show Gist options
  • Save louthy/4dfe2268c657dbf53a166a8a165e6b11 to your computer and use it in GitHub Desktop.
Save louthy/4dfe2268c657dbf53a166a8a165e6b11 to your computer and use it in GitHub Desktop.
Echo - Prelude fs
namespace Echo
open LanguageExt
open LanguageExt.UnitsOfMeasure
open System
open Microsoft.FSharp.Data.UnitSystems.SI.UnitNames
module ProcessFs =
type SessionId = Echo.SessionId
type ProcessId = Echo.ProcessId
type ProcessName = Echo.ProcessName
let DefaultFlags =
ProcessFlags.Default
let PersistInbox =
ProcessFlags.PersistInbox
let PersistState =
ProcessFlags.PersistState
let RemotePublish =
ProcessFlags.RemotePublish
let PersistAll =
ProcessFlags.PersistAll
let Self =
new ProcessId("/__special__/self")
let Parent =
new ProcessId("/__special__/parent")
let User =
new ProcessId("/__special__/user")
let DeadLetters =
new ProcessId("/__special__/dead-letters")
let Registered =
new ProcessId("/__special__/registered")
let Sender =
new ProcessId("/__special__/sender")
let Root =
new ProcessId("/__special__/root")
let Errors =
new ProcessId("/__special__/errors")
let NoSender =
ProcessId.NoSender
let isSenderValid () =
Process.Sender.IsValid
let isSelfValid () =
Process.Self.IsValid
let resolvePID (pid:ProcessId) : ProcessId =
Process.resolvePID(pid)
let childrenSelf() : FSharp.Collections.Map<string,ProcessId> =
FSharp.fs(Process.Children)
let children pid : FSharp.Collections.Map<string,ProcessId> =
FSharp.fs(Process.children(pid |> resolvePID))
// Used to represent the lack of a setup function for a Process
let NoSetup() = ()
// Used to coerce a stateless inbox function into one that takes a unit state
let NoState (inbox:'msg -> unit) =
(fun (_:unit) (msg:'msg) -> inbox msg |> ignore)
/// Find a process by its *registered* name (a kind of DNS for Processes).
///
/// Multiple Processes can register under the same name. You may use
/// a dispatcher to work on them collectively (wherever they are in the
/// cluster). i.e.
///
/// var regd = register "proc" pid
/// tell DispatchFs.Broadcast.[regd] "Hello" Self
/// tell DispatchFs.First.[regd] "Hello" Self
/// tell DispatchFs.LeastBusy.[regd] "Hello" Self
/// tell DispatchFs.Random.[regd] "Hello" Self
/// tell DispatchFs.RoundRobin.[regd] "Hello" Self
let findProcess name =
Process.find(new ProcessName(name))
/// Register a named process (a kind of DNS for Processes).
///
/// If the Process is visible to the cluster (PersistInbox) then the
/// registration becomes a permanent named look-up until Process.deregister
/// is called.
///
/// Multiple Processes can register under the same name. You may use
/// a dispatcher to work on them collectively (wherever they are in the
/// cluster). i.e.
///
/// var regd = registerSelf proc
/// tell DispatchFs.Broadcast.[regd] "Hello" Self
/// tell DispatchFs.First.[regd] "Hello" Self
/// tell DispatchFs.LeastBusy.[regd] "Hello" Self
/// tell DispatchFs.Random.[regd] "Hello" Self
/// tell DispatchFs.RoundRobin.[regd] "Hello" Self
///
/// This should be used from within a process' message loop only
let registerSelf name =
Process.register(new ProcessName(name))
/// Register a named process (a kind of DNS for Processes).
///
/// If the Process is visible to the cluster (PersistInbox) then the
/// registration becomes a permanent named look-up until Process.deregister
/// is called.
///
/// Multiple Processes can register under the same name. You may use
/// a dispatcher to work on them collectively (wherever they are in the
/// cluster). i.e.
///
/// var regd = register "proc" pid
/// tell DispatchFs.Broadcast.[regd] "Hello" Self
/// tell DispatchFs.First.[regd] "Hello" Self
/// tell DispatchFs.LeastBusy.[regd] "Hello" Self
/// tell DispatchFs.Random.[regd] "Hello" Self
/// tell DispatchFs.RoundRobin.[regd] "Hello" Self
///
/// This should be used from within a process' message loop only
let register name processId system =
Process.register(new ProcessName(name), resolvePID processId)
/// Deregister all Processes associated with a name. NOTE: Be very careful
/// with usage of this function if you didn't handle the registration you
/// are potentially disconnecting many Processes from their registered name.
///
/// Any Process (or dispatcher, or role, etc.) can be registered by a name -
/// a kind of DNS for ProcessIds. There can be multiple names associated
/// with a single ProcessId and multiple ProcessIds associated with a name.
///
/// This function removes all registered ProcessIds for a specific name.
/// If you wish to deregister all names registered for specific Process then
/// use deregisterById pid
let deregisterByName name =
Process.deregisterByName(new ProcessName(name)) |> ignore
/// Deregister a Process from any names it's been registered as.
///
/// Any Process (or dispatcher, or role, etc.) can be registered by a name -
/// a kind of DNS for ProcessIds. There can be multiple names associated
/// with a single ProcessId.
///
/// This function removes all registered names for a specific ProcessId.
/// If you wish to deregister all ProcessIds registered under a name then
/// use deregisterByName name
let deregisterById pid =
Process.deregisterById(resolvePID pid) |> ignore
let killSelf() =
Process.kill |> ignore
let kill pid =
Process.kill(resolvePID pid) |> ignore
let shutdownAll() =
Process.shutdownAll() |> ignore
let isAsk () =
Process.isAsk
/// Reply to an ask
let reply msg : unit =
Process.reply msg |> ignore
/// Reply if asked
let replyIfAsked msg : unit =
Process.replyIfAsked msg |> ignore
/// Reply to the asker, or if it's not an ask then tell the sender
/// via a message to their inbox.
let replyOrTellSender msg : unit =
Process.replyOrTellSender msg |> ignore
let ask pid (message : 'a) : 'b =
Process.ask<'b>(resolvePID pid, message)
let askChildren (message : 'a) : 'b seq =
Process.askChildren<'b>(message,Int32.MaxValue)
let askChildrenTake (message : 'a) count : 'b seq =
Process.askChildren<'b>(message,count)
let askChildrenFirst (message : 'a) =
askChildrenTake message 1
let askParent (message : 'a) : 'b =
Process.askParent message
let askChild name (message : 'a) : 'b =
Process.askChild(new ProcessName(name), message)
let askChildByIndex (index:int) (message : 'a) : 'b =
Process.askChild(index, message)
let tell pid message sender =
Process.tell(resolvePID pid,message,resolvePID sender) |> ignore
let tellDelay pid message (delay:TimeSpan) sender =
Process.tell(resolvePID pid,message,delay,resolvePID sender)
let tellChildren message sender =
Process.tellChildren(message,resolvePID sender) |> ignore
let tellChildrenDelay message (delay:TimeSpan) sender =
Process.tellChildren(message,delay,resolvePID sender)
let tellChild name message sender =
Process.tellChild(new ProcessName(name), message, resolvePID sender) |> ignore
let tellChildByIndex (index:int) message sender =
Process.tellChild(index, message, resolvePID sender) |> ignore
let tellParent message sender =
Process.tellParent (message, resolvePID sender) |> ignore
let tellParentDelay message (delay:TimeSpan) sender =
Process.tellParent(message,delay, resolvePID sender)
let tellSelf message =
Process.tellSelf(message,Process.Self) |> ignore
let tellSelfDelay message (delay:TimeSpan) =
Process.tellSelf(message,delay,Process.Self)
let publish message =
Process.publish message |> ignore
let publishDelay message (delay:TimeSpan) =
Process.publish(message, delay) |> ignore
let subscribe pid =
Process.subscribe(resolvePID pid) |> ignore
let observe pid =
Process.observe(resolvePID pid);
let spawn name flags setup messageHandler =
Process.spawn(new ProcessName(name), new Func<'state>(setup), new Func<'state, 'msg, 'state>(messageHandler), flags)
let spawnMany count name flags setup messageHandler =
Process.spawnMany(count, new ProcessName(name), new Func<'state>(setup), new Func<'state, 'msg, 'state>(messageHandler), flags)
|> Seq.map(fun pid -> pid)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment