Просмотр исходного кода

ActorLocation使用ActorLocationSender来实现,实现大大简化

tanghai 6 лет назад
Родитель
Сommit
031443794a

+ 67 - 168
Server/Hotfix/Module/ActorLocation/ActorLocationSenderSystem.cs

@@ -9,25 +9,18 @@ namespace ETHotfix
         public override void Awake(ActorLocationSender self)
         {
             self.LastRecvTime = TimeHelper.Now();
-            self.Tcs = null;
             self.FailTimes = 0;
             self.ActorId = 0;
-            self.WaitingTasks.Clear();
+            
+            StartAsync(self).Coroutine();
         }
-    }
-
-    [ObjectSystem]
-    public class ActorLocationSenderStartSystem : StartSystem<ActorLocationSender>
-    {
-	    public override void Start(ActorLocationSender self)
-	    {
-		    StartAsync(self).Coroutine();
-	    }
-	    
+        
         public async ETVoid StartAsync(ActorLocationSender self)
         {
-            self.ActorId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
-            self.UpdateAsync().Coroutine();
+	        using (await CoroutineLockComponent.Instance.Wait(self.Id))
+	        {
+		        self.ActorId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
+	        }
         }
     }
 	
@@ -36,192 +29,98 @@ namespace ETHotfix
     {
         public override void Destroy(ActorLocationSender self)
         {
-	        self.RunError(ErrorCode.ERR_ActorRemove);
-	        
             self.Id = 0;
             self.LastRecvTime = 0;
             self.ActorId = 0;
             self.FailTimes = 0;
-            self.WaitingTasks.Clear();
-            self.Tcs = null;
         }
     }
     
-    public static class ActorLocationSenderHelper
+    public static class ActorLocationSenderSystem
     {
-    	private static void Add(this ActorLocationSender self, ActorTask task)
+		private static async ETTask<IActorResponse> Run(this ActorLocationSender self, IActorRequest iActorRequest)
 		{
-			if (self.IsDisposed)
-			{
-				throw new Exception("ActorLocationSender Disposed! dont hold ActorMessageSender");
-			}
-
-			self.WaitingTasks.Enqueue(task);
-			// failtimes > 0表示正在重试,这时候不能加到正在发送队列
-			if (self.FailTimes == 0)
+			long instanceId = self.InstanceId;
+			using (await CoroutineLockComponent.Instance.Wait(self.Id))
 			{
-				self.AllowGet();
-			}
-		}
-
-	    public static void RunError(this ActorLocationSender self, int errorCode)
-	    {
-		    while (self.WaitingTasks.Count > 0)
-		    {
-			    ActorTask actorTask = self.WaitingTasks.Dequeue();
-			    actorTask.Tcs?.SetException(new RpcException(errorCode, ""));
-		    }
-		    self.WaitingTasks.Clear();
-	    }
-
-		private static void AllowGet(this ActorLocationSender self)
-		{
-			if (self.Tcs == null || self.WaitingTasks.Count <= 0)
-			{
-				return;
-			}
-
-			ActorTask task = self.WaitingTasks.Peek();
-
-			var t = self.Tcs;
-			self.Tcs = null;
-			t.SetResult(task);
-		}
-
-		private static ETTask<ActorTask> GetAsync(this ActorLocationSender self)
-		{
-			if (self.WaitingTasks.Count > 0)
-			{
-				ActorTask task = self.WaitingTasks.Peek();
-				return ETTask.FromResult(task);
-			}
-
-			self.Tcs = new ETTaskCompletionSource<ActorTask>();
-			return self.Tcs.Task;
-		}
-
-		public static async ETVoid UpdateAsync(this ActorLocationSender self)
-		{
-			try
-			{
-				long instanceId = self.InstanceId;
-				while (true)
+				if (self.InstanceId != instanceId)
 				{
-					ActorTask actorTask = await self.GetAsync();
-					
-					if (self.InstanceId != instanceId)
-					{
-						return;
-					}
+					throw new RpcException(ErrorCode.ERR_ActorRemove, "");
+				}
+				
+				ActorMessageSender actorMessageSender = Game.Scene.GetComponent<ActorMessageSenderComponent>().Get(self.ActorId);
+				try
+				{
+					// ERR_NotFoundActor是需要抛异常的,但是这里不能抛
+					IActorResponse response = await actorMessageSender.CallWithoutException(iActorRequest);
 					
-					if (actorTask.ActorRequest == null)
+					switch (response.Error)
 					{
-						return;
+						case ErrorCode.ERR_NotFoundActor:
+							// 如果没找到Actor,重试
+							++self.FailTimes;
+
+							// 失败MaxFailTimes次则清空actor发送队列,返回失败
+							if (self.FailTimes > ActorLocationSender.MaxFailTimes)
+							{
+								// 失败直接删除actorproxy
+								Log.Info($"actor send message fail, actorid: {self.Id}");
+								self.GetParent<ActorLocationSenderComponent>().Remove(self.Id);
+								throw new RpcException(response.Error, "");
+							}
+
+							// 等待0.5s再发送
+							await Game.Scene.GetComponent<TimerComponent>().WaitAsync(500);
+							if (self.InstanceId != instanceId)
+							{
+								throw new RpcException(ErrorCode.ERR_ActorRemove, "");
+							}
+							self.ActorId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
+							IActorResponse iActorResponse = await Run(self, iActorRequest);
+							if (self.InstanceId != instanceId)
+							{
+								throw new RpcException(ErrorCode.ERR_ActorRemove, "");
+							}
+							return iActorResponse;
+
+						case ErrorCode.ERR_ActorNoMailBoxComponent:
+							self.GetParent<ActorLocationSenderComponent>().Remove(self.Id);
+							throw new RpcException(response.Error, "");
+
+						default:
+							self.LastRecvTime = TimeHelper.Now();
+							self.FailTimes = 0;
+							break;
 					}
-
-					await self.RunTask(actorTask);
 					
-					if (self.InstanceId != instanceId)
-					{
-						return;
-					}
+					return response;
 				}
-			}
-			catch (Exception e)
-			{
-				Log.Error(e);
-			}
-		}
-
-		private static async ETTask RunTask(this ActorLocationSender self, ActorTask task)
-		{
-			ActorMessageSender actorMessageSender = Game.Scene.GetComponent<ActorMessageSenderComponent>().Get(self.ActorId);
-			IActorResponse response;
-			try
-			{
-				// 这里必须使用不抛异常的rpc,因为服务端handler很可能出现错误,返回一个rpc fail的错误,结果这里抛了异常
-				// 这里抛了异常就会导致队列中的消息无法继续发送,导致整个actorlocationsender堵塞
-				response = await actorMessageSender.CallWithoutException(task.ActorRequest);
-			}
-			catch (Exception e)
-			{
-				self.GetParent<ActorLocationSenderComponent>().Remove(self.Id);
-				return;
-			}
-			
-			
-			// 发送成功
-			switch (response.Error)
-			{
-				case ErrorCode.ERR_NotFoundActor:
-					// 如果没找到Actor,重试
-					++self.FailTimes;
-
-					// 失败MaxFailTimes次则清空actor发送队列,返回失败
-					if (self.FailTimes > ActorLocationSender.MaxFailTimes)
-					{
-						// 失败直接删除actorproxy
-						Log.Info($"actor send message fail, actorid: {self.Id}");
-						self.RunError(response.Error);
-						self.GetParent<ActorLocationSenderComponent>().Remove(self.Id);
-						return;
-					}
-
-					// 等待0.5s再发送
-					await Game.Scene.GetComponent<TimerComponent>().WaitAsync(500);
-					self.ActorId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
-					self.AllowGet();
-					return;
-				
-				case ErrorCode.ERR_ActorNoMailBoxComponent:
-					self.RunError(response.Error);
+				catch (Exception)
+				{
 					self.GetParent<ActorLocationSenderComponent>().Remove(self.Id);
-					return;
-				
-				default:
-					self.LastRecvTime = TimeHelper.Now();
-					self.FailTimes = 0;
-					self.WaitingTasks.Dequeue();
-
-					// 如果所有的发送消息都得到了返回,发送任务完成,那么删除这个ActorLocationSender,及时回收发送对象
-					if (self.WaitingTasks.Count == 0)
-					{
-						self.GetParent<ActorLocationSenderComponent>().Remove(self.Id);
-					}
-					
-					if (task.Tcs != null)
-					{
-						IActorLocationResponse actorLocationResponse = response as IActorLocationResponse;
-						if (actorLocationResponse == null)
-						{
-							task.Tcs.SetException(new Exception($"actor location respose is not IActorLocationResponse, but is: {response.GetType().Name}"));
-						}
-						task.Tcs.SetResult(actorLocationResponse);
-					}
-					return;
+					throw;
+				}
 			}
 		}
 
-	    public static void Send(this ActorLocationSender self, IActorLocationMessage request)
+	    public static async ETVoid Send(this ActorLocationSender self, IActorLocationMessage request)
 	    {
 		    if (request == null)
 		    {
 			    throw new Exception($"actor location send message is null");
 		    }
-		    ActorTask task = new ActorTask(request);
-		    self.Add(task);
+		    
+			await Run(self, request);
 	    }
 
-		public static ETTask<IActorLocationResponse> Call(this ActorLocationSender self, IActorLocationRequest request)
+		public static async ETTask<IActorLocationResponse> Call(this ActorLocationSender self, IActorLocationRequest request)
 		{
 			if (request == null)
 			{
 				throw new Exception($"actor location call message is null");
 			}
-			ETTaskCompletionSource<IActorLocationResponse> tcs = new ETTaskCompletionSource<IActorLocationResponse>();
-			ActorTask task = new ActorTask(request, tcs);
-			self.Add(task);
-			return task.Tcs.Task;
+			
+			return await Run(self, request) as IActorLocationResponse;
 		}
     }
 }

+ 0 - 5
Server/Model/Module/ActorLocation/ActorLocationSender.cs

@@ -8,17 +8,12 @@ namespace ETModel
 	{
 		public long ActorId;
 		
-		// 还没发送的消息
-		public Queue<ActorTask> WaitingTasks = new Queue<ActorTask>();
-
 		// 最近接收消息的时间
 		public long LastRecvTime;
 		
 		public int FailTimes;
 
 		public const int MaxFailTimes = 5;
-		
-		public ETTaskCompletionSource<ActorTask> Tcs;
 
 		public override void Dispose()
 		{

+ 3 - 3
Server/Model/Server.Model.csproj

@@ -47,9 +47,6 @@
     <Compile Include="..\..\Unity\Assets\Model\Base\Async\MoveNextRunner.cs">
       <Link>Base\Async\MoveNextRunner.cs</Link>
     </Compile>
-    <Compile Include="..\..\Unity\Assets\Model\Base\CoroutineLockComponent.cs">
-      <Link>Base\CoroutineLockComponent.cs</Link>
-    </Compile>
     <Compile Include="..\..\Unity\Assets\Model\Base\Helper\MongoHelper.cs">
       <Link>Base\Helper\MongoHelper.cs</Link>
     </Compile>
@@ -71,6 +68,9 @@
     <Compile Include="..\..\Unity\Assets\Model\Module\Config\AConfigComponent.cs">
       <Link>Module\Config\AConfigComponent.cs</Link>
     </Compile>
+    <Compile Include="..\..\Unity\Assets\Model\Module\CoroutineLock\CoroutineLockComponent.cs">
+      <Link>Module\CoroutineLock\CoroutineLockComponent.cs</Link>
+    </Compile>
     <Compile Include="..\..\Unity\Assets\Model\Module\Message\MessagePool.cs">
       <Link>Module\Message\MessagePool\ETModel\MessagePool.cs</Link>
     </Compile>

+ 8 - 0
Unity/Assets/Model/Module/CoroutineLock.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f47e6303eab9c4df8bee0778b82709e3
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 0 - 0
Unity/Assets/Model/Base/CoroutineLockComponent.cs → Unity/Assets/Model/Module/CoroutineLock/CoroutineLockComponent.cs


+ 1 - 1
Unity/Assets/Model/Base/CoroutineLockComponent.cs.meta → Unity/Assets/Model/Module/CoroutineLock/CoroutineLockComponent.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 0ca564c89e8bb4d61b3720d67fc2edaf
+guid: 4b0a6eacd974f4ce1bf0213d5105fab4
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2

+ 1 - 1
Unity/Unity.Model.csproj

@@ -70,7 +70,6 @@
     <Compile Include="Assets\Model\Base\Async\ETVoid.cs" />
     <Compile Include="Assets\Model\Base\Async\IAwaiter.cs" />
     <Compile Include="Assets\Model\Base\Async\MoveNextRunner.cs" />
-    <Compile Include="Assets\Model\Base\CoroutineLockComponent.cs" />
     <Compile Include="Assets\Model\Base\DoubleMap.cs" />
     <Compile Include="Assets\Model\Base\Event\Env.cs" />
     <Compile Include="Assets\Model\Base\Event\EnvKey.cs" />
@@ -303,6 +302,7 @@
     <Compile Include="Assets\Model\Module\Config\ConfigComponent.cs" />
     <Compile Include="Assets\Model\Module\Config\ConfigHelper.cs" />
     <Compile Include="Assets\Model\Module\Config\IConfig.cs" />
+    <Compile Include="Assets\Model\Module\CoroutineLock\CoroutineLockComponent.cs" />
     <Compile Include="Assets\Model\Module\Demo\AnimatorComponent.cs" />
     <Compile Include="Assets\Model\Module\Demo\CameraComponent.cs" />
     <Compile Include="Assets\Model\Module\Demo\Config\UnitConfig.cs" />