ActorLocationSenderSystem.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. using ETModel;
  6. namespace ETHotfix
  7. {
  8. [ObjectSystem]
  9. public class ActorLocationSenderAwakeSystem : AwakeSystem<ActorLocationSender, long>
  10. {
  11. public override void Awake(ActorLocationSender self, long id)
  12. {
  13. self.LastSendTime = TimeHelper.Now();
  14. self.Id = id;
  15. self.Tcs = null;
  16. self.FailTimes = 0;
  17. self.ActorId = 0;
  18. }
  19. }
  20. [ObjectSystem]
  21. public class ActorLocationSenderStartSystem : StartSystem<ActorLocationSender>
  22. {
  23. public override void Start(ActorLocationSender self)
  24. {
  25. StartAsync(self).NoAwait();
  26. }
  27. public async ETVoid StartAsync(ActorLocationSender self)
  28. {
  29. self.ActorId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
  30. self.Address = StartConfigComponent.Instance
  31. .Get(IdGenerater.GetAppIdFromId(self.ActorId))
  32. .GetComponent<InnerConfig>().IPEndPoint;
  33. self.UpdateAsync().NoAwait();
  34. }
  35. }
  36. [ObjectSystem]
  37. public class ActorLocationSenderDestroySystem : DestroySystem<ActorLocationSender>
  38. {
  39. public override void Destroy(ActorLocationSender self)
  40. {
  41. self.RunError(ErrorCode.ERR_ActorRemove);
  42. self.Id = 0;
  43. self.LastSendTime = 0;
  44. self.Address = null;
  45. self.ActorId = 0;
  46. self.FailTimes = 0;
  47. self.Tcs = null;
  48. }
  49. }
  50. public static class ActorLocationSenderHelper
  51. {
  52. private static void Add(this ActorLocationSender self, ActorTask task)
  53. {
  54. if (self.IsDisposed)
  55. {
  56. throw new Exception("ActorLocationSender Disposed! dont hold ActorMessageSender");
  57. }
  58. self.WaitingTasks.Enqueue(task);
  59. // failtimes > 0表示正在重试,这时候不能加到正在发送队列
  60. if (self.FailTimes == 0)
  61. {
  62. self.AllowGet();
  63. }
  64. }
  65. public static void RunError(this ActorLocationSender self, int errorCode)
  66. {
  67. while (self.WaitingTasks.Count > 0)
  68. {
  69. ActorTask actorTask = self.WaitingTasks.Dequeue();
  70. actorTask.Tcs?.SetException(new RpcException(errorCode, ""));
  71. }
  72. self.WaitingTasks.Clear();
  73. }
  74. private static void AllowGet(this ActorLocationSender self)
  75. {
  76. if (self.Tcs == null || self.WaitingTasks.Count <= 0)
  77. {
  78. return;
  79. }
  80. ActorTask task = self.WaitingTasks.Peek();
  81. var t = self.Tcs;
  82. self.Tcs = null;
  83. t.SetResult(task);
  84. }
  85. private static ETTask<ActorTask> GetAsync(this ActorLocationSender self)
  86. {
  87. if (self.WaitingTasks.Count > 0)
  88. {
  89. ActorTask task = self.WaitingTasks.Peek();
  90. return ETTask.FromResult(task);
  91. }
  92. self.Tcs = new ETTaskCompletionSource<ActorTask>();
  93. return self.Tcs.Task;
  94. }
  95. public static async ETVoid UpdateAsync(this ActorLocationSender self)
  96. {
  97. try
  98. {
  99. long instanceId = self.InstanceId;
  100. while (true)
  101. {
  102. if (self.InstanceId != instanceId)
  103. {
  104. return;
  105. }
  106. ActorTask actorTask = await self.GetAsync();
  107. if (self.InstanceId != instanceId)
  108. {
  109. return;
  110. }
  111. if (actorTask.ActorRequest == null)
  112. {
  113. return;
  114. }
  115. await self.RunTask(actorTask);
  116. }
  117. }
  118. catch (Exception e)
  119. {
  120. Log.Error(e);
  121. }
  122. }
  123. private static async Task RunTask(this ActorLocationSender self, ActorTask task)
  124. {
  125. ActorMessageSender actorMessageSender = Game.Scene.GetComponent<ActorMessageSenderComponent>().Get(self.ActorId);
  126. IActorResponse response = await actorMessageSender.Call(task.ActorRequest);
  127. // 发送成功
  128. switch (response.Error)
  129. {
  130. case ErrorCode.ERR_NotFoundActor:
  131. // 如果没找到Actor,重试
  132. ++self.FailTimes;
  133. // 失败MaxFailTimes次则清空actor发送队列,返回失败
  134. if (self.FailTimes > ActorLocationSender.MaxFailTimes)
  135. {
  136. // 失败直接删除actorproxy
  137. Log.Info($"actor send message fail, actorid: {self.Id}");
  138. self.RunError(response.Error);
  139. self.GetParent<ActorLocationSenderComponent>().Remove(self.Id);
  140. return;
  141. }
  142. // 等待0.5s再发送
  143. await Game.Scene.GetComponent<TimerComponent>().WaitAsync(500);
  144. self.ActorId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
  145. self.Address = StartConfigComponent.Instance
  146. .Get(IdGenerater.GetAppIdFromId(self.ActorId))
  147. .GetComponent<InnerConfig>().IPEndPoint;
  148. self.AllowGet();
  149. return;
  150. case ErrorCode.ERR_ActorNoMailBoxComponent:
  151. self.RunError(response.Error);
  152. self.GetParent<ActorLocationSenderComponent>().Remove(self.Id);
  153. return;
  154. default:
  155. self.LastSendTime = TimeHelper.Now();
  156. self.FailTimes = 0;
  157. self.WaitingTasks.Dequeue();
  158. if (task.Tcs == null)
  159. {
  160. return;
  161. }
  162. IActorLocationResponse actorLocationResponse = response as IActorLocationResponse;
  163. if (actorLocationResponse == null)
  164. {
  165. task.Tcs.SetException(new Exception($"actor location respose is not IActorLocationResponse, but is: {response.GetType().Name}"));
  166. }
  167. task.Tcs.SetResult(actorLocationResponse);
  168. return;
  169. }
  170. }
  171. public static void Send(this ActorLocationSender self, IActorLocationMessage request)
  172. {
  173. if (request == null)
  174. {
  175. throw new Exception($"actor location send message is null");
  176. }
  177. ActorTask task = new ActorTask(request);
  178. self.Add(task);
  179. }
  180. public static ETTask<IActorLocationResponse> Call(this ActorLocationSender self, IActorLocationRequest request)
  181. {
  182. if (request == null)
  183. {
  184. throw new Exception($"actor location call message is null");
  185. }
  186. ETTaskCompletionSource<IActorLocationResponse> tcs = new ETTaskCompletionSource<IActorLocationResponse>();
  187. ActorTask task = new ActorTask(request, tcs);
  188. self.Add(task);
  189. return task.Tcs.Task;
  190. }
  191. }
  192. }