public IFuture <StreamItemContainer <TResult> > Stream <TResult>(string target, params object[] args) { var future = new Future <StreamItemContainer <TResult> >(); long id = InvokeImp(target, args, callback: (message) => { switch (message.type) { // StreamItem message contains only one item. case Messages.MessageTypes.StreamItem: { var container = future.value; if (container.IsCanceled) { break; } container.AddItem((TResult)this.Protocol.ConvertTo(typeof(TResult), message.item)); // (re)assign the container to raise OnItem event future.AssignItem(container); break; } case Messages.MessageTypes.Completion: { bool isSuccess = string.IsNullOrEmpty(message.error); if (isSuccess) { var container = future.value; // While completion message must not contain any result, this should be future-proof //if (!container.IsCanceled && message.Result != null) //{ // TResult[] results = (TResult[])this.Protocol.ConvertTo(typeof(TResult[]), message.Result); // // container.AddItems(results); //} future.Assign(container); } else { future.Fail(new Exception(message.error)); } break; } } }, isStreamingInvocation: true); future.BeginProcess(new StreamItemContainer <TResult>(id)); return(future); }
public UpStreamItemController <TResult> GetUpStreamController <TResult>(string target, int paramCount, bool downStream = false) { Future <TResult> future = new Future <TResult>(); future.BeginProcess(); long invocationId = System.Threading.Interlocked.Increment(ref this.lastInvocationId); string[] streamIds = new string[paramCount]; for (int i = 0; i < paramCount; i++) { streamIds[i] = System.Threading.Interlocked.Increment(ref this.lastStreamId).ToString(); } var controller = new UpStreamItemController <TResult>(this, invocationId, streamIds, future); Action <Message> callback = (Message msg) => { switch (msg.type) { // StreamItem message contains only one item. case MessageTypes.StreamItem: { if (controller.IsCanceled) { break; } TResult item = (TResult)this.Protocol.ConvertTo(typeof(TResult), msg.item); future.AssignItem(item); break; } case MessageTypes.Completion: { bool isSuccess = string.IsNullOrEmpty(msg.error); if (isSuccess) { // While completion message must not contain any result, this should be future-proof if (!controller.IsCanceled && msg.result != null) { TResult result = (TResult)this.Protocol.ConvertTo(typeof(TResult), msg.result); future.AssignItem(result); } future.Finish(); } else { var ex = new Exception(msg.error); future.Fail(ex); } break; } } }; var messageToSend = new Message { type = downStream ? MessageTypes.StreamInvocation : MessageTypes.Invocation, invocationId = invocationId.ToString(), target = target, arguments = new object[0], streamIds = streamIds, nonblocking = false, }; SendMessage(messageToSend); this.invocations.Add(invocationId, new InvocationDefinition { callback = callback, returnType = typeof(TResult) }); return(controller); }
public DownStreamItemController <TDown> GetDownStreamController <TDown>(string target, params object[] args) { long invocationId = System.Threading.Interlocked.Increment(ref this.lastInvocationId); var future = new Future <TDown>(); future.BeginProcess(); var controller = new DownStreamItemController <TDown>(this, invocationId, future); Action <Message> callback = (Message msg) => { switch (msg.type) { // StreamItem message contains only one item. case MessageTypes.StreamItem: { if (controller.IsCanceled) { break; } TDown item = (TDown)this.Protocol.ConvertTo(typeof(TDown), msg.item); future.AssignItem(item); break; } case MessageTypes.Completion: { bool isSuccess = string.IsNullOrEmpty(msg.error); if (isSuccess) { // While completion message must not contain any result, this should be future-proof if (!controller.IsCanceled && msg.result != null) { TDown result = (TDown)this.Protocol.ConvertTo(typeof(TDown), msg.result); future.AssignItem(result); } future.Finish(); } else { future.Fail(new Exception(msg.error)); } break; } } }; var message = new Message { type = MessageTypes.StreamInvocation, invocationId = invocationId.ToString(), target = target, arguments = args, nonblocking = false, }; SendMessage(message); if (callback != null) { this.invocations.Add(invocationId, new InvocationDefinition { callback = callback, returnType = typeof(TDown) }); } return(controller); }
internal UploadItemController <StreamItemContainer <TResult> > UploadStreamWithDownStream <TResult>(string target, int paramCount) { Future <StreamItemContainer <TResult> > future = new Future <StreamItemContainer <TResult> >(); Action <Message> callback = (Message message) => { switch (message.type) { // StreamItem message contains only one item. case MessageTypes.StreamItem: { StreamItemContainer <TResult> container = future.value; if (container.IsCanceled) { break; } container.AddItem((TResult)this.Protocol.ConvertTo(typeof(TResult), message.item)); // (re)assign the container to raise OnItem event future.AssignItem(container); break; } case MessageTypes.Completion: { bool isSuccess = string.IsNullOrEmpty(message.error); if (isSuccess) { StreamItemContainer <TResult> container = future.value; // While completion message must not contain any result, this should be future-proof if (!container.IsCanceled && message.result != null) { TResult result = (TResult)this.Protocol.ConvertTo(typeof(TResult), message.result); container.AddItem(result); } future.Assign(container); } else { future.Fail(new Exception(message.error)); } break; } } }; long invocationId = System.Threading.Interlocked.Increment(ref this.lastInvocationId); int[] streamIds = new int[paramCount]; for (int i = 0; i < paramCount; i++) { streamIds[i] = System.Threading.Interlocked.Increment(ref this.lastStreamId); } var controller = new UploadItemController <StreamItemContainer <TResult> >(this, invocationId, streamIds, future); var messageToSend = new Message { type = MessageTypes.StreamInvocation, invocationId = invocationId.ToString(), target = target, arguments = new object[0], streamIds = streamIds, nonblocking = false, }; SendMessage(messageToSend); this.invocations.Add(invocationId, callback); future.BeginProcess(new StreamItemContainer <TResult>(invocationId)); return(controller); }