Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
JsonRpcClientRequest.cs
1using System;
3using System.IO;
4using System.Threading.Tasks;
5using Waher.Content;
6using Waher.Events;
7
9{
14 {
15 private readonly JsonRpcWebService webService;
16 private readonly IJsonRpcSession session;
17 private readonly TaskCompletionSource<T> result;
18 private readonly Func<object?, Task<T>> parseResult;
19 private readonly HttpRequest httpRequest;
20 private readonly string method;
21 private readonly object? parameters;
22 private bool processed = false;
23
24 internal JsonRpcClientRequest(string Message, object? Id, string Method,
25 object? Parameters, IJsonRpcSession Session, Func<object?, Task<T>> ParseResult,
27 {
28 this.Message = Message;
29 this.Id = Id;
30 this.method = Method;
31 this.parameters = Parameters;
32 this.session = Session;
33 this.parseResult = ParseResult;
34 this.webService = WebService;
35 this.httpRequest = HttpRequest;
36 this.result = new TaskCompletionSource<T>();
37 }
38
42 public string Message { get; }
43
47 public object? Id { get; }
48
53 public object? Tag { get; set; }
54
59 public async Task ReportResult(object? Result)
60 {
61 try
62 {
63 if (!(Result is T ParsedResult))
64 ParsedResult = await this.parseResult(Result);
65
66 await this.Return(ParsedResult);
67 }
68 catch (Exception ex)
69 {
70 await this.Error(ex);
71 }
72 }
73
77 public async Task Cancel()
78 {
79 if (!this.processed)
80 {
81 this.processed = true;
82 this.webService.RemoveClientRequest(this.Id?.ToString() ?? string.Empty);
83 this.result.TrySetCanceled();
84
85 await this.Cancelled.Raise(this, EventArgs.Empty);
86 }
87 }
88
93
99 public Task ReportError(int? ErrorCode, string ErrorMessage)
100 {
101 if (!this.processed)
102 {
103 this.processed = true;
104 this.webService.RemoveClientRequest(this.Id?.ToString() ?? string.Empty);
105 this.result.TrySetException(new Exception(ErrorMessage));
106
107 // Note: Do not raise event. Not an error in processing; the request was not sent or received properly.
108 }
109
110 return Task.CompletedTask;
111 }
112
117 public async Task Return(T Result)
118 {
119 if (!this.processed)
120 {
121 this.processed = true;
122 this.webService.RemoveClientRequest(this.Id?.ToString() ?? string.Empty);
123 this.result.TrySetResult(Result);
124
125 await this.ResultReturned.Raise(this, EventArgs.Empty);
126 }
127 }
128
133
138 public async Task Error(Exception Error)
139 {
140 if (!this.processed)
141 {
142 this.processed = true;
143 this.webService.RemoveClientRequest(this.Id?.ToString() ?? string.Empty);
144 this.result.TrySetException(Error);
145
146 await this.ErrorReturned.Raise(this, EventArgs.Empty);
147 }
148 }
149
154
158 [Obsolete("Use DisposeAsync instead.")]
159 public void Dispose()
160 {
161 this.DisposeAsync().Wait();
162 }
163
167 public Task DisposeAsync()
168 {
169 return this.Cancel();
170 }
171
175 public async Task SendRequest()
176 {
177 Dictionary<string, object?> Request = new Dictionary<string, object?>()
178 {
179 { "jsonrpc", "2.0" },
180 { "id", this.Id },
181 { "method", this.method },
182 { "params", this.parameters }
183 };
184 string Data = JSON.Encode(Request, false);
185
186 int NrSent = await this.webService.SendEvent(
187 Session =>
188 {
189 if (this.session.SessionId != Session?.SessionId)
190 return false;
191
192 this.session.TransmitText(Data);
193
194 return true;
195 },
196 new KeyValuePair<string, object>("event", "message"),
197 new KeyValuePair<string, object>("data", Data));
198
199 if (NrSent == 0)
200 {
201 this.webService.RemoveClientRequest(this.Id?.ToString() ?? string.Empty);
202 throw new IOException("Session no longer active.");
203 }
204 }
205
211 public async Task<T> WaitForResultAsync(int Timeout)
212 {
213 TaskCompletionSource<bool> Completed = new TaskCompletionSource<bool>();
214
215 async void KeepAlive(TaskCompletionSource<bool> Completed, int Timeout)
216 {
217 DateTime Start = DateTime.UtcNow;
218 DateTime Until = Start.AddMilliseconds(Timeout);
219 DateTime TP;
220
221 try
222 {
223 while (!Completed.Task.IsCompleted && (TP = DateTime.UtcNow) < Until)
224 {
225 this.httpRequest.Ping();
226 await Task.Delay(Math.Min(1000, (int)Until.Subtract(TP).TotalMilliseconds));
227 }
228
229 if (!Completed.Task.IsCompleted)
230 await this.Error(new TimeoutException());
231 }
232 catch (Exception ex)
233 {
234 Log.Exception(ex);
235 }
236 }
237
238 KeepAlive(Completed, Timeout);
239
240 try
241 {
242 return await this.result.Task;
243 }
244 finally
245 {
246 Completed.TrySetResult(true);
247 }
248 }
249 }
250}
Helps with common JSON-related tasks.
Definition: JSON.cs:16
static string Encode(string s)
Encodes a string for inclusion in JSON.
Definition: JSON.cs:537
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1657
Represents an HTTP request.
Definition: HttpRequest.cs:22
Represents a request made to a JSON-RPC client.
EventHandlerAsync? Cancelled
Event raised when the request has been cancelled.
EventHandlerAsync? ErrorReturned
Event raised when an error has been returned for the request.
Task ReportError(int? ErrorCode, string ErrorMessage)
Called when an error is received for the request.
async Task< T > WaitForResultAsync(int Timeout)
Waits for a response to the request.
async Task Return(T Result)
Returns a result for the request.
async Task ReportResult(object? Result)
Called when a result is received for the request.
object? Tag
Property that can be used to store user-defined data associated with the request.
Task DisposeAsync()
Disposes of the object, asynchronously.
async Task SendRequest()
Sends the request to the MCP client.
async Task Cancel()
Called when the input dialog has been cancelled.
async Task Error(Exception Error)
Returns an error for the request.
EventHandlerAsync? ResultReturned
Event raised when a result has been returned for the request.
Abstract base class for Web Services based on JSON-RPC v2.0.
Interface for asynchronously disposable objects.
Interface for JSON-RPC client request objects.
Interface for JSON-RPC session objects.
void TransmitText(string Text)
Is called when text has been transmitted.
delegate string ToString(IElement Element)
Delegate for callback methods that convert an element value to a string.
delegate Task EventHandlerAsync(object Sender, EventArgs e)
Asynchronous version of EventArgs.