public static Map <A, Map <B, Map <C, D> > > AddOrUpdate <A, B, C, D>(this Map <A, Map <B, Map <C, D> > > self, A aKey, B bKey, C cKey, D value) => self.AddOrUpdate( aKey, bKey, c => c.AddOrUpdate(cKey, _ => value, value), () => Prelude.Map(Tuple(cKey, value)) );
public static Map <A, Map <B, Map <C, D> > > AddOrUpdate <A, B, C, D>(this Map <A, Map <B, Map <C, D> > > self, A aKey, B bKey, C cKey, Func <D, D> Some, Func <D> None) => self.AddOrUpdate( aKey, bKey, c => c.AddOrUpdate(cKey, Some, None), () => Prelude.Map(Tuple(cKey, None())) );
/// <summary> /// Gains a child process /// </summary> public Unit LinkChild(ActorItem item) { lock (sync) { children = children.AddOrUpdate(item.Actor.Id.GetName().Value, item); } return(unit); }
public static Map <A, Map <B, Map <C, Map <D, E> > > > AddOrUpdate <A, B, C, D, E>(this Map <A, Map <B, Map <C, Map <D, E> > > > self, A aKey, B bKey, C cKey, D dKey, E value) => self.AddOrUpdate( aKey, bKey, cKey, d => d.AddOrUpdate(dKey, _ => value, value), () => Prelude.Map(Tuple(dKey, value)) );
public static ProcessId AddDispatcher(ProcessName name, Func <ProcessId, IEnumerable <ProcessId> > selector) { lock (sync) { dispatchers = dispatchers.AddOrUpdate(name, selector); } return(ProcessId.Top["disp"][name]); }
public static Map <A, Map <B, Map <C, Map <D, E> > > > AddOrUpdate <A, B, C, D, E>(this Map <A, Map <B, Map <C, Map <D, E> > > > self, A aKey, B bKey, C cKey, D dKey, Func <E, E> Some, Func <E> None) => self.AddOrUpdate( aKey, bKey, cKey, d => d.AddOrUpdate(dKey, Some, None), () => Prelude.Map(Tuple(dKey, None())) );
public static Unit AddWatcher(ProcessId watcher, ProcessId watching) { Process.logInfo(watcher + " is watching " + watching); lock (sync) { watchers = watchers.AddOrUpdate(watching, Some: set => set.AddOrUpdate(watcher), None: () => Set(watcher) ); watchings = watchings.AddOrUpdate(watcher, Some: set => set.AddOrUpdate(watching), None: () => Set(watching) ); } return(unit); }
static void AddLocalRegistered(ProcessName name, ProcessId pid) { lock (regsync) { registeredProcessNames = registeredProcessNames.AddOrUpdate(name, Some: set => set.AddOrUpdate(pid), None: () => Set(pid) ); registeredProcessIds = registeredProcessIds.AddOrUpdate(pid, Some: set => set.AddOrUpdate(name), None: () => Set(name) ); } }
/// <summary> /// Provider registration /// </summary> /// <param name="name">Name</param> /// <param name="provider">Function that generates a new cluster based on provided config</param> /// <returns>Unit</returns> public static Unit RegisterProvider(string name, Func <ClusterConfig, ICluster> provider) { if (name == null) { throw new ArgumentNullException(nameof(name)); } if (String.IsNullOrWhiteSpace(name)) { throw new ArgumentException(nameof(name)); } if (provider == null) { throw new ArgumentNullException(nameof(provider)); } lock (sync) { providers = providers.AddOrUpdate(name, provider); return(unit); } }
static MethodInfo DeserialiseFunc(Type type) { var name = type.FullName; var result = funcs.Find(name); if (result.IsSome) { return(result.LiftUnsafe()); } var func = typeof(JsonConvert).GetTypeInfo() .GetDeclaredMethods("DeserializeObject") .Filter(m => m.IsGenericMethod) .Filter(m => m.GetParameters().Length == 1) .Head() .MakeGenericMethod(type); // No locks because we don't really care if it's done // more than once, but we do care about locking unnecessarily. funcs = funcs.AddOrUpdate(name, func); return(func); }
/// <summary> /// Retrieve a value from the map by key, map it to a new value, /// put it back. If it doesn't exist, add a new one based on None result. /// </summary> /// <param name="key">Key to find</param> /// <exception cref="ArgumentNullException">Throws ArgumentNullException if None is null</exception> /// <exception cref="Exception">Throws Exception if Some returns null</exception> /// <returns>New map with the mapped value</returns> public static Map <K, V> addOrUpdate <K, V>(Map <K, V> map, K key, Func <V, V> Some, V None) => map.AddOrUpdate(key, Some, None);
static Dispatch() { ProcessName broadcast = "broadcast"; ProcessName leastBusy = "least-busy"; ProcessName random = "random"; ProcessName roundRobin = "round-robin"; ProcessName first = "first"; ProcessName second = "second"; ProcessName third = "third"; ProcessName last = "last"; var processes = fun((ProcessId leaf) => { if (!leaf.IsValid) { return(new ProcessId[0]); } if (leaf.IsSelection) { return(leaf.GetSelection()); } if (leaf.Head().Name == "disp") { leaf = leaf.Skip(1); if (!leaf.IsValid) { return(new ProcessId[0]); } return(getFunc(leaf.Head().Name)(leaf.Skip(1))); } return(new ProcessId[1] { leaf }); }); // Broadcast Broadcast = register(broadcast, processes); // First First = register(first, leaf => processes(leaf).Take(1)); // Second Second = register(second, leaf => processes(leaf).Skip(1).Take(1)); // Third Third = register(third, leaf => processes(leaf).Skip(2).Take(1)); // Last Last = register(last, leaf => processes(leaf).Reverse().Take(1)); // Least busy LeastBusy = register(leastBusy, leaf => processes(leaf) .Map(pid => Tuple(inboxCount(pid), pid)) .OrderBy(tup => tup.Item1) .Map(tup => tup.Item2) .Take(1)); // Random Random = register(random, leaf => { var workers = processes(leaf).ToArray(); return(new ProcessId[1] { workers[Prelude.random(workers.Length)] }); }); // Round-robin object sync = new object(); Map <string, int> roundRobinState = Map.empty <string, int>(); RoundRobin = register(roundRobin, leaf => { var key = leaf.ToString(); var workers = processes(leaf).ToArray(); int index = 0; lock (sync) { roundRobinState = roundRobinState.AddOrUpdate(key, x => { index = x % workers.Length; return(x + 1); }, 0); } return(new ProcessId[1] { workers[index] }); }); }
public State SetMember(ProcessName nodeName, ClusterNode state) => state == null ? RemoveMember(nodeName) : new State(Members.AddOrUpdate(nodeName, state), System);
public State SetSession(string sid, Session session) => SetSessions(Sessions.AddOrUpdate(sid, session));
/// <summary> /// Atomically adds a new item to the map. /// If the key already exists, the new item replaces it. /// </summary> /// <remarks>Null is not allowed for a Key or a Value</remarks> /// <param name="key">Key</param> /// <param name="value">Value</param> /// <exception cref="ArgumentNullException">Throws ArgumentNullException the key or value are null</exception> /// <returns>New Map with the item added</returns> public static Map <K, V> addOrUpdate <K, V>(Map <K, V> map, K key, V value) => map.AddOrUpdate(key, value);
/// <summary> /// Static ctor /// Sets up the default roles /// </summary> static Role() { ProcessName first = "role-first"; ProcessName second = "role-second"; ProcessName third = "role-third"; ProcessName last = "role-last"; ProcessName next = "role-next"; ProcessName prev = "role-prev"; ProcessName broadcast = "role-broadcast"; ProcessName leastBusy = "role-least-busy"; ProcessName random = "role-random"; ProcessName roundRobin = "role-round-robin"; var nextNode = fun((bool fwd) => fun((ProcessId leaf) => { var self = leaf.Take(1).GetName(); var isNext = false; var nodeMap = Nodes(leaf); var nodes = fwd ? nodeMap.Values.Append(nodeMap.Values) : nodeMap.Values.Append(nodeMap.Values).Reverse(); //< TODO: Inefficient foreach (var node in nodes) { if (isNext) { return(new[] { ProcessId.Top[node.NodeName].Append(leaf.Skip(1)) }.AsEnumerable()); } if (node.NodeName == self) { isNext = true; } } return(new ProcessId[0].AsEnumerable()); })); // Next nextRoot = Dispatch.register(next, nextNode(true)); // Prev prevRoot = Dispatch.register(prev, nextNode(false)); // First First = Dispatch.register(first, leaf => NodeIds(leaf).Take(1)); // Second Second = Dispatch.register(second, leaf => NodeIds(leaf).Skip(1).Take(1)); // Third Third = Dispatch.register(third, leaf => NodeIds(leaf).Skip(2).Take(1)); // Last Last = Dispatch.register(last, leaf => NodeIds(leaf).Reverse().Take(1)); // Broadcast Broadcast = Dispatch.register(broadcast, NodeIds); // Least busy LeastBusy = Dispatch.register(leastBusy, leaf => NodeIds(leaf) .Map(pid => Tuple(inboxCount(pid), pid)) .OrderBy(tup => tup.Item1) .Map(tup => tup.Item2) .Take(1)); // Random Random = Dispatch.register(random, leaf => { var workers = NodeIds(leaf).ToArray(); return(new ProcessId[1] { workers[Prelude.random(workers.Length)] }); }); // Round-robin object sync = new object(); Map <string, int> roundRobinState = Map.empty <string, int>(); RoundRobin = Dispatch.register(roundRobin, leaf => { var key = leaf.ToString(); var workers = NodeIds(leaf).ToArray(); int index = 0; lock (sync) { roundRobinState = roundRobinState.AddOrUpdate(key, x => { index = x % workers.Length; return(x + 1); }, 0); } return(new ProcessId[1] { workers[index] }); }); }
public static Map <A, Map <B, C> > AddOrUpdate <A, B, C>(this Map <A, Map <B, C> > self, A outerKey, B innerKey, Func <C, C> Some, Func <C> None) => self.AddOrUpdate( outerKey, b => b.AddOrUpdate(innerKey, Some, None), () => Prelude.Map(Tuple(innerKey, None())) );
public State SetMetadatum(string sid, object metadatum) => SetMetadata(Metadata.AddOrUpdate(sid, metadatum));
public static Map <A, Map <B, C> > AddOrUpdate <A, B, C>(this Map <A, Map <B, C> > self, A outerKey, B innerKey, C value) => self.AddOrUpdate( outerKey, b => b.AddOrUpdate(innerKey, _ => value, value), () => Prelude.Map(Tuple(innerKey, value)) );
/// <summary> /// Adds or updates an item of meta-data /// /// This is for extending the default strategies behaviours and /// allows for state to survive in-between Process errors /// </summary> public StrategyState SetMetaData <T>(string key, T value) => With(Metadata: Metadata.AddOrUpdate(key, value));
public State SetMember(ProcessName nodeName, ClusterNode state) => new State(Members.AddOrUpdate(nodeName, state));