-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathPrelude_Ask.cs
131 lines (121 loc) · 5.63 KB
/
Prelude_Ask.cs
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
using LanguageExt;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using static LanguageExt.Prelude;
using static Echo.Process;
namespace Echo
{
/// <summary>
/// <para>
/// Process: Ask functions
/// </para>
/// <para>
/// 'ask' is a request/response system for processes. You can ask a process a question (a message) and it
/// can reply using the 'Process.reply' function. It doesn't have to and 'ask' will timeout after
/// ActorConfig.Default.Timeout seconds.
/// </para>
/// <para>
/// 'ask' is blocking, because mostly it will be called from within a process and processes shouldn't
/// perform asynchronous operations.
/// </para>
/// </summary>
public static partial class Process
{
/// <summary>
/// Ask a process for a reply
/// </summary>
/// <param name="pid">Process to ask</param>
/// <param name="message">Message to send</param>
/// <param name="sender">Sender process</param>
/// <returns>The response to the request</returns>
public static T ask<T>(ProcessId pid, object message, ProcessId sender) =>
ActorContext.System(pid).Ask<T>(pid, message, sender);
/// <summary>
/// Ask a process for a reply
/// </summary>
/// <param name="pid">Process to ask</param>
/// <param name="message">Message to send</param>
/// <returns>The response to the request</returns>
public static T ask<T>(ProcessId pid, object message) =>
ask<T>(pid, message, Self);
/// <summary>
/// Asynchronous ask - must be used outside of a Process
/// </summary>
/// <typeparam name="R">Type of the return value</typeparam>
/// <param name="pid">Process to ask</param>
/// <param name="message">Message to send</param>
/// <param name="sender">Sender process</param>
/// <returns>A promise to return a response to the request</returns>
public static Task<R> askAsync<R>(ProcessId pid, object message, ProcessId sender) =>
InMessageLoop
? raiseDontUseInMessageLoopException<Task<R>>(nameof(observeState))
: Task.Run(() => ask<R>(pid, message, sender));
/// <summary>
/// Ask a process for a reply (if the process is running). If the process isn't running
/// then None is returned
/// </summary>
/// <param name="pid">Process to ask</param>
/// <param name="message">Message to send</param>
/// <param name="sender">Sender process</param>
/// <returns>The response to the request or None if the process isn't running</returns>
public static Option<T> askIfAlive<T>(ProcessId pid, object message, ProcessId sender) =>
ping(pid)
? Optional(ActorContext.System(pid).Ask<T>(pid, message, sender))
: None;
/// <summary>
/// Ask a process for a reply (if the process is running). If the process isn't running
/// then None is returned
/// </summary>
/// <param name="pid">Process to ask</param>
/// <param name="message">Message to send</param>
/// <returns>The response to the request or None if the process isn't running</returns>
public static Option<T> askIfAlive<T>(ProcessId pid, object message) =>
ping(pid)
? Optional(ask<T>(pid, message, Self))
: None;
/// <summary>
/// Asynchronous ask - must be used outside of a Process
/// </summary>
/// <typeparam name="R">Type of the return value</typeparam>
/// <param name="pid">Process to ask</param>
/// <param name="message">Message to send</param>
/// <returns>A promise to return a response to the request</returns>
public static Task<R> askAsync<R>(ProcessId pid, object message) =>
askAsync<R>(pid, message, Self);
/// <summary>
/// Ask children the same message
/// </summary>
/// <param name="message">Message to send</param>
/// <returns></returns>
public static IEnumerable<T> askChildren<T>(object message, int take = Int32.MaxValue) =>
ActorContext.System(default(SystemName)).AskMany<T>(Children.Values, message, take);
/// <summary>
/// Ask parent process for a reply
/// </summary>
/// <param name="message">Message to send</param>
/// <returns>The response to the request</returns>
public static T askParent<T>(object message) =>
ask<T>(Parent, message);
/// <summary>
/// Ask a named child process for a reply
/// </summary>
/// <param name="message">Message to send</param>
/// <param name="name">Name of the child process</param>
public static T askChild<T>(ProcessName name, object message) =>
ask<T>(Self.Child(name), message);
/// <summary>
/// Ask a child process (found by index) for a reply
/// </summary>
/// <remarks>
/// Because of the potential changeable nature of child nodes, this will
/// take the index and mod it by the number of children. We expect this
/// call will mostly be used for load balancing, and round-robin type
/// behaviour, so feel that's acceptable.
/// </remarks>
/// <param name="message">Message to send</param>
/// <param name="index">Index of the child process (see remarks)</param>
public static T askChild<T>(int index, object message) =>
ask<T>(child(index), message);
}
}