Skip to content

Commit d6e945d

Browse files
committed
implemented proper command center handling with batches and ability to resend. this also fixes maintenance and network errors.
1 parent c2708dd commit d6e945d

File tree

17 files changed

+554
-119
lines changed

17 files changed

+554
-119
lines changed

HTTPRequest/HTTPRequest.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public static HttpWebRequest Post(string url, string contentType, byte[] postDat
5454
}
5555

5656
// Make a connection and send the request
57-
WritePostData (httpRequest, postData, (Exception requestError) => {
57+
WritePostData(httpRequest, postData, (Exception requestError) => {
5858
if (requestError != null) {
5959
cb(requestError, null);
6060
return;
@@ -84,11 +84,6 @@ private static void WritePostData (HttpWebRequest httpRequest, byte[] postData,
8484
private static void ReadResponseData (HttpWebRequest httpRequest, Action<Exception, string> cb) {
8585
httpRequest.BeginGetResponse(new AsyncCallback((IAsyncResult callbackResult) => {
8686
string responseString = null;
87-
if (!httpRequest.HaveResponse) {
88-
cb(null, responseString);
89-
return;
90-
}
91-
9287
try {
9388
HttpWebResponse response = (HttpWebResponse)httpRequest.EndGetResponse(callbackResult);
9489

JSONRPC/JSONRPC.cs

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,30 @@
77
using Newtonsoft.Json.Linq;
88

99
public class JSONRPC {
10+
// Endpoint and Basic Authentication
1011
private string _endpoint;
11-
12-
// Basic authentication
1312
private string _username = null;
1413
private string _password = null;
1514

16-
public void setEndpoint(string endpoint, string username = null, string password = null) {
15+
public void SetEndpoint(string endpoint, string username = null, string password = null) {
1716
_endpoint = endpoint;
1817
_username = username;
1918
_password = password;
2019
}
2120

22-
public void call(string methodName, JObject parameters, Dictionary<string, string> headers, CookieContainer cookies, Action<Exception, JObject> cb) {
23-
call(JValue.CreateNull(), methodName, parameters, headers, cookies, cb);
21+
public void Call(string methodName, JObject parameters, Dictionary<string, string> headers, CookieContainer cookies, Action<Exception, JObject> cb) {
22+
Call(JValue.CreateNull(), methodName, parameters, headers, cookies, cb);
2423
}
2524

26-
public void call(string id, string methodName, JObject parameters, Dictionary<string, string> headers, CookieContainer cookies, Action<Exception, JObject> cb) {
27-
call(new JValue(id), methodName, parameters, headers, cookies, cb);
25+
public void Call(string id, string methodName, JObject parameters, Dictionary<string, string> headers, CookieContainer cookies, Action<Exception, JObject> cb) {
26+
Call(new JValue(id), methodName, parameters, headers, cookies, cb);
2827
}
2928

30-
public void call(int id, string methodName, JObject parameters, Dictionary<string, string> headers, CookieContainer cookies, Action<Exception, JObject> cb) {
31-
call(new JValue(id), methodName, parameters, headers, cookies, cb);
29+
public void Call(int id, string methodName, JObject parameters, Dictionary<string, string> headers, CookieContainer cookies, Action<Exception, JObject> cb) {
30+
Call(new JValue(id), methodName, parameters, headers, cookies, cb);
3231
}
3332

34-
public void call(JValue id, string methodName, JObject parameters, Dictionary<string, string> headers, CookieContainer cookies, Action<Exception, JObject> cb) {
35-
// Make sure the endpoint is set
36-
if (string.IsNullOrEmpty(_endpoint)) {
37-
cb(new Exception("Endpoint has not been set"), null);
38-
return;
39-
}
40-
33+
public void Call(JValue id, string methodName, JObject parameters, Dictionary<string, string> headers, CookieContainer cookies, Action<Exception, JObject> cb) {
4134
// Setup JSON request object
4235
JObject requestObject = new JObject ();
4336
requestObject.Add("jsonrpc", new JValue("2.0"));
@@ -55,31 +48,72 @@ public void call(JValue id, string methodName, JObject parameters, Dictionary<st
5548
return;
5649
}
5750

58-
// Make a copy of the provided headers and add additional required headers
59-
Dictionary<string, string> _headers = new Dictionary<string, string>(headers);
60-
if (_username != null && _password != null) {
61-
string authInfo = _username + ":" + _password;
62-
string encodedAuth = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
63-
_headers.Add("Authorization", "Basic " + encodedAuth);
64-
}
65-
66-
// Send HTTP post to JSON rpc endpoint
67-
HTTPRequest.Post(_endpoint, "application/json", postData, _headers, cookies, (Exception requestError, string responseString) => {
51+
// Send request
52+
SendRequest(postData, headers, cookies, (Exception requestError, string responseString) => {
6853
if (requestError != null) {
6954
cb(requestError, null);
7055
return;
7156
}
72-
57+
7358
// Deserialize the JSON response
7459
JObject responseObject;
7560
try {
7661
responseObject = JObject.Parse(responseString);
77-
} catch (Exception error) {
78-
cb(error, null);
62+
} catch (Exception parseError) {
63+
cb(parseError, null);
7964
return;
8065
}
81-
66+
8267
cb(null, responseObject);
8368
});
8469
}
70+
71+
public void CallBatch(JSONRPCBatch rpcBatch, Dictionary<string, string> headers, CookieContainer cookies, Action<Exception, JArray> cb) {
72+
// Serialize JSON request object into string
73+
string postData;
74+
try {
75+
postData = rpcBatch.batch.ToString();
76+
} catch (Exception serializeError) {
77+
cb(serializeError, null);
78+
return;
79+
}
80+
81+
// Send request
82+
SendRequest(postData, headers, cookies, (Exception requestError, string responseString) => {
83+
if (requestError != null) {
84+
cb(requestError, null);
85+
return;
86+
}
87+
88+
// Deserialize the JSON response
89+
JArray responseArray;
90+
try {
91+
responseArray = JArray.Parse(responseString);
92+
} catch (Exception parseError) {
93+
cb(parseError, null);
94+
return;
95+
}
96+
97+
cb(null, responseArray);
98+
});
99+
}
100+
101+
private void SendRequest(string postData, Dictionary<string, string> headers, CookieContainer cookies, Action<Exception, string> cb) {
102+
// Make sure the endpoint is set
103+
if (string.IsNullOrEmpty(_endpoint)) {
104+
cb(new Exception("Endpoint has not been set"), null);
105+
return;
106+
}
107+
108+
// Make a copy of the provided headers and add additional required headers
109+
Dictionary<string, string> _headers = new Dictionary<string, string>(headers);
110+
if (_username != null && _password != null) {
111+
string authInfo = _username + ":" + _password;
112+
string encodedAuth = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
113+
_headers.Add("Authorization", "Basic " + encodedAuth);
114+
}
115+
116+
// Send HTTP post to JSON rpc endpoint
117+
HTTPRequest.Post(_endpoint, "application/json", postData, _headers, cookies, cb);
118+
}
85119
}

JSONRPC/JSONRPCBatch.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using Newtonsoft.Json.Linq;
2+
3+
public class JSONRPCBatch {
4+
public JArray batch = new JArray();
5+
6+
public void Add(string methodName, JObject parameters) {
7+
Add(JValue.CreateNull(), methodName, parameters);
8+
}
9+
10+
public void Add(string id, string methodName, JObject parameters) {
11+
Add(new JValue(id), methodName, parameters);
12+
}
13+
14+
public void Add(int id, string methodName, JObject parameters) {
15+
Add(new JValue(id), methodName, parameters);
16+
}
17+
18+
public void Add(JValue id, string methodName, JObject parameters) {
19+
JObject requestObject = new JObject();
20+
requestObject.Add("jsonrpc", new JValue("2.0"));
21+
22+
requestObject.Add("id", id);
23+
requestObject.Add("method", new JValue(methodName));
24+
requestObject.Add("params", parameters);
25+
26+
batch.Add(requestObject);
27+
}
28+
}

Mage/Archivist/Archivist.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ public Dictionary<string, VaultValue> GetCache() {
119119

120120

121121
// Clear out the cache entirely
122+
// NOTE: we create a new instance as the Clear() function is not thread safe.
122123
public void ClearCache() {
123124
_cache = new Dictionary<string, VaultValue>();
124125
}
@@ -242,15 +243,15 @@ private void rawGet(string topic, JObject index, Action<Exception, JToken> cb) {
242243
parameters.Add("topic", topic);
243244
parameters.Add("index", index);
244245

245-
mage.rpcClient.call ("archivist.rawGet", parameters, cb);
246+
mage.commandCenter.SendCommand("archivist.rawGet", parameters, cb);
246247
}
247248

248249
private void rawMGet(JToken queries, JObject options, Action<Exception, JToken> cb) {
249250
JObject parameters = new JObject();
250251
parameters.Add(new JProperty ("queries", queries));
251252
parameters.Add("options", options);
252253

253-
mage.rpcClient.call ("archivist.rawMGet", parameters, cb);
254+
mage.commandCenter.SendCommand("archivist.rawMGet", parameters, cb);
254255
}
255256

256257
private void rawList(string topic, JObject partialIndex, JObject options, Action<Exception, JToken> cb) {
@@ -259,7 +260,7 @@ private void rawList(string topic, JObject partialIndex, JObject options, Action
259260
parameters.Add("partialIndex", partialIndex);
260261
parameters.Add("options", options);
261262

262-
mage.rpcClient.call ("archivist.rawList", parameters, cb);
263+
mage.commandCenter.SendCommand("archivist.rawList", parameters, cb);
263264
}
264265

265266
private void rawSet(string topic, JObject index, JToken data, string mediaType, string encoding, string expirationTime, Action<Exception, JToken> cb) {
@@ -271,15 +272,15 @@ private void rawSet(string topic, JObject index, JToken data, string mediaType,
271272
parameters.Add ("encoding", new JValue(encoding));
272273
parameters.Add ("expirationTime", new JValue(expirationTime));
273274

274-
mage.rpcClient.call ("archivist.rawSet", parameters, cb);
275+
mage.commandCenter.SendCommand("archivist.rawSet", parameters, cb);
275276
}
276277

277278
private void rawDel(string topic, JObject index, Action<Exception, JToken> cb) {
278279
JObject parameters = new JObject();
279280
parameters.Add ("topic", new JValue(topic));
280281
parameters.Add ("index", index);
281282

282-
mage.rpcClient.call ("archivist.rawDel", parameters, cb);
283+
mage.commandCenter.SendCommand("archivist.rawDel", parameters, cb);
283284
}
284285

285286

Mage/CommandCenter/CommandBatch.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
using Newtonsoft.Json.Linq;
5+
6+
7+
public class CommandBatch {
8+
public int queryId;
9+
public List<CommandBatchItem> batchItems = new List<CommandBatchItem>();
10+
11+
public CommandBatch(int queryId) {
12+
this.queryId = queryId;
13+
}
14+
15+
public void Queue(string commandName, JObject parameters, Action<Exception, JToken> cb) {
16+
batchItems.Add(new CommandBatchItem(commandName, parameters, cb));
17+
}
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
3+
using Newtonsoft.Json.Linq;
4+
5+
6+
public class CommandBatchItem {
7+
public string commandName;
8+
public JObject parameters;
9+
public Action<Exception, JToken> cb;
10+
11+
public CommandBatchItem(string commandName, JObject parameters, Action<Exception, JToken> cb) {
12+
this.commandName = commandName;
13+
this.parameters = parameters;
14+
this.cb = cb;
15+
}
16+
}

0 commit comments

Comments
 (0)