private async ValueTask ProcessInvokeRequire(int msgId, string service, BytesSegment frame, int offset) { //设置当前会话,TODO:考虑在后面设置 RuntimeContext.Current.CurrentSession = Session; //注意:不要使用Task.ContinueWith, 异常会传播至上级 try { var hostCtx = ((HostRuntimeContext)RuntimeContext.Current); var res = await hostCtx.InvokeByClient(service, msgId, InvokeArgs.From(frame, offset)); await SendInvokeResponse(msgId, res); } catch (Exception ex) { await SendInvokeResponse(msgId, AnyValue.From(ex)); Log.Warn($"Invoke error: {ExceptionHelper.GetExceptionDetailInfo(ex)}"); } }
public void ReadArgsTest1() { var js = "\"A\":[4, \"2660935927-4\", \"HelloService\"]"; var data = System.Text.Encoding.UTF8.GetBytes(js); var segment = BytesSegment.Rent(); //data.AsSpan(4).CopyTo(segment.Buffer.AsSpan()); //segment.Length = data.Length - 4; //Assert.Equal(System.Text.Encoding.UTF8.GetString(segment.Memory.Span), // "[4, \"2660935927-4\", \"HelloService\"]"); data.AsSpan().CopyTo(segment.Buffer); segment.Length = data.Length; var args = InvokeArgs.From(segment, 4); Assert.True(args.GetInt32() == 4); Assert.True(args.GetString() == "2660935927-4"); Assert.True(args.GetString() == "HelloService"); }
public void ReadArgsTest2() { var mockRunntimeContext = new MockRuntimeContext(); Runtime.RuntimeContext.Init(mockRunntimeContext, 10410); mockRunntimeContext.AddModel(TestHelper.EmploeeModel); var js = "\"A\":[{\"$T\":\"111428632783249997828\",\"Id\":\"01200000-0020-016e-fa64-547f10410001\",\"Name\":\"Sales Dept\"},\"01200000-0020-016e-fa64-547f10410001\"]"; var data = System.Text.Encoding.UTF8.GetBytes(js); var segment = BytesSegment.Rent(); data.AsSpan().CopyTo(segment.Buffer); segment.Length = data.Length; var args = InvokeArgs.From(segment, 4); var obj = args.GetObject(); Assert.True(obj != null); var id = args.GetGuid(); Assert.True(id == Guid.Parse("01200000-0020-016e-fa64-547f10410001")); }
public async Task Invoke(HttpContext context) { //暂简单处理,读请求数据至缓存块,然后走与WebSocket相同的流程 //待实现Utf8JsonReaderStream后再修改 int bytesRead = 0; int totalBytes = (int)context.Request.ContentLength.Value; BytesSegment frame = null; while (bytesRead < totalBytes) //TODO:读错误归还缓存块 { var temp = BytesSegment.Rent(); int len = await context.Request.Body.ReadAsync(temp.Buffer.AsMemory()); temp.Length = len; bytesRead += len; if (frame != null) { frame.Append(temp); } frame = temp; } //1. 解析请求头 int msgId = 0; string service = null; //TODO:优化不创建string int offset = 0; //偏移量至参数数组开始,不包含[Token AnyValue res = AnyValue.Empty; try { offset = InvokeHelper.ReadRequireHead(frame.First, ref msgId, ref service); if (offset == -1) //没有参数 { BytesSegment.ReturnOne(frame); } } catch (Exception ex) { res = AnyValue.From(ex); BytesSegment.ReturnAll(frame); //读消息头异常归还缓存块 Log.Warn($"收到无效的Api调用请求: {ex.Message}\n{ex.StackTrace}"); } //2. 设置当前会话并调用服务 if (res.ObjectValue == null) { var webSession = context.Session.LoadWebSession(); RuntimeContext.Current.CurrentSession = webSession; try { var hostCtx = (HostRuntimeContext)RuntimeContext.Current; res = await hostCtx.InvokeByClient(service, 0, InvokeArgs.From(frame, offset)); } catch (Exception ex) { Log.Warn($"调用服务异常: {ex.Message}\n{ex.StackTrace}"); res = AnyValue.From(ex); } } //3. 返回结果,注意:FileResult特殊类型统一由BlobController处理 context.Response.ContentType = "application/json"; if (res.Type == AnyValueType.Object && res.ObjectValue is BytesSegment) { var cur = (ReadOnlySequenceSegment <byte>)res.ObjectValue; try { while (cur != null) { await context.Response.Body.WriteAsync(cur.Memory); cur = cur.Next; } } catch (Exception ex) { Log.Warn($"Send InvokeResponse to ajax error: {ex.Message}"); } finally { BytesSegment.ReturnAll((BytesSegment)res.ObjectValue); //注意归还缓存块 } } else { res.SerializeAsInvokeResponse(context.Response.Body, 0);//TODO:序列化错误处理 } }