【特性】Luban.Client支持watch机制,监测相关定义或数据改变后自动重新生成。节省迭代时间。

main
walon 2021-05-08 15:08:27 +08:00
parent 1129b5f458
commit 35f0af394a
5 changed files with 115 additions and 15 deletions

View File

@ -67,6 +67,7 @@ Luban适合有以下需求的开发者
- unity + c# - unity + c#
- unity + tolua,xlua - unity + tolua,xlua
- unity + ILRuntime - unity + ILRuntime
- unity + puerts
- unreal + c++ - unreal + c++
- unreal + unlua - unreal + unlua
- unreal + sluaunreal - unreal + sluaunreal

View File

@ -2,8 +2,8 @@
"profiles": { "profiles": {
"Luban.Client": { "Luban.Client": {
"commandName": "Project", "commandName": "Project",
"commandLineArgs": "-h 127.0.0.1 -p 8899 -j cfg -a \"{ 'define_file':'../../CfgDefines/root.xml', 'input_data_dir':'../../CfgDatas', 'validate_root_dir':'E:/NikkiP4_D/X6Game/Content', 'output_data_dir':'output_data', 'service':'server', 'export_test_data':true,'gen_types':'code_cs_bin,data_bin', 'output_code_dir' : 'Gen' }\"", "commandLineArgs": "-h %LUBAN_SERVER_IP% -j cfg -w ..\\DesignerConfigs\\Datas -- -d ..\\DesignerConfigs\\Defines\\__root__.xml --input_data_dir ..\\DesignerConfigs\\Datas --output_code_dir TsScripts/src/Gen/Cfg --output_data_dir ConfigData --gen_types code_typescript_bin,data_bin -s client --export_test_data --validate_root_dir Assets ",
"workingDirectory": "E:\\workspace\\bright_gen\\DemoProjects\\Csharp_Server_DotNetCore" "workingDirectory": "C:\\workspace\\unity-world\\Client"
}, },
"Luban.Client-db": { "Luban.Client-db": {
"commandName": "Project", "commandName": "Project",

View File

@ -32,10 +32,11 @@ namespace Luban.Client.Common.Net
private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger(); private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
public static GenClient Ins { get; } = new GenClient(); public static GenClient Ins { get; private set; }
public async Task Start(string host, int port, Dictionary<int, ProtocolCreator> factories) public static async Task Start(string host, int port, Dictionary<int, ProtocolCreator> factories)
{ {
Ins = new GenClient();
var c = new TcpClientBootstrap var c = new TcpClientBootstrap
{ {
RemoteAddress = new IPEndPoint(IPAddress.Parse(host), port), RemoteAddress = new IPEndPoint(IPAddress.Parse(host), port),
@ -44,13 +45,19 @@ namespace Luban.Client.Common.Net
InitHandler = ch => InitHandler = ch =>
{ {
ch.Pipeline.AddLast(new ProtocolFrameCodec(20_000_000, new RecycleByteBufPool(100, 10), new DefaultProtocolAllocator(factories))); ch.Pipeline.AddLast(new ProtocolFrameCodec(20_000_000, new RecycleByteBufPool(100, 10), new DefaultProtocolAllocator(factories)));
ch.Pipeline.AddLast(this); ch.Pipeline.AddLast(Ins);
} }
}; };
var ch = await c.ConnectAsync().ConfigureAwait(false); var ch = await c.ConnectAsync().ConfigureAwait(false);
} }
public static void Stop()
{
_ = Ins.Session.CloseAsync();
Ins = null;
}
public override void HandleProtocol(Protocol proto) public override void HandleProtocol(Protocol proto)
{ {

View File

@ -4,6 +4,7 @@ using Luban.Common.Protos;
using Luban.Common.Utils; using Luban.Common.Utils;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -25,10 +26,14 @@ namespace Luban.Client
public bool Verbose { get; set; } public bool Verbose { get; set; }
public string CacheMetaInfoFile { get; set; } = ".cache.meta"; public string CacheMetaInfoFile { get; set; } = ".cache.meta";
public string WatchDir { get; set; }
} }
private static NLog.Logger s_logger; private static NLog.Logger s_logger;
private static FileSystemWatcher s_watcher;
private static void PrintUsage(string err) private static void PrintUsage(string err)
{ {
Console.WriteLine("ERRORS:"); Console.WriteLine("ERRORS:");
@ -39,11 +44,12 @@ e.g.
Luban.Client -h 127.0.0.1 -p 2234 -j cfg -- --name abc Luban.Client -h 127.0.0.1 -p 2234 -j cfg -- --name abc
Options: Options:
-h, --host Required. host ip -h, --host <host> Required. host ip
-p --port port. default 8899 -p --port <port> port. default 8899
-j --job Required. job type. avaliable value: cfg -j --job <job> Required. job type. avaliable value: cfg
-v --verbose verbose print -v --verbose verbose print
-c --cachemetafile cache meta file name -c --cachemetafile <file> cache meta file name. default is '.cache.meta'
-w --watch <dir> watch data change and regenerate.
-h --help show usage -h --help show usage
"); ");
} }
@ -90,6 +96,12 @@ Options:
ops.CacheMetaInfoFile = args[++i]; ops.CacheMetaInfoFile = args[++i];
break; break;
} }
case "-w":
case "--watch":
{
ops.WatchDir = args[++i];
break;
}
case "--": case "--":
{ {
++i; ++i;
@ -135,7 +147,6 @@ Options:
CommandLineOptions options = parseResult.Item2; CommandLineOptions options = parseResult.Item2;
profile.StartPhase("init logger"); profile.StartPhase("init logger");
LogUtil.InitSimpleNLogConfigure(NLog.LogLevel.Info); LogUtil.InitSimpleNLogConfigure(NLog.LogLevel.Info);
s_logger = NLog.LogManager.GetCurrentClassLogger(); s_logger = NLog.LogManager.GetCurrentClassLogger();
profile.EndPhaseAndLog(); profile.EndPhaseAndLog();
@ -143,14 +154,82 @@ Options:
ThreadPool.SetMinThreads(4, 5); ThreadPool.SetMinThreads(4, 5);
ThreadPool.SetMaxThreads(64, 10); ThreadPool.SetMaxThreads(64, 10);
if (string.IsNullOrWhiteSpace(options.WatchDir))
{
Environment.Exit(GenOnce(options, profile));
profile.EndPhaseAndLog();
}
else
{
GenOnce(options, profile);
var watcher = new FileSystemWatcher(options.WatchDir);
watcher.NotifyFilter = NotifyFilters.Attributes
| NotifyFilters.CreationTime
| NotifyFilters.DirectoryName
| NotifyFilters.FileName
| NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.Security
| NotifyFilters.Size;
watcher.Changed += (o, p) => OnWatchChange(options, profile);
watcher.Created += (o, p) => OnWatchChange(options, profile);
watcher.Deleted += (o, p) => OnWatchChange(options, profile);
watcher.Renamed += (o, p) => OnWatchChange(options, profile);
//watcher.Filter = "*.txt";
watcher.IncludeSubdirectories = true;
watcher.EnableRaisingEvents = true;
s_logger.Info("=== start watch. dir:{} ==", options.WatchDir);
s_watcher = watcher;
}
}
private static readonly object s_watchLocker = new object();
private static bool s_watchDirChange = false;
private static void OnWatchChange(CommandLineOptions options, ProfileTimer profile)
{
lock (s_watchLocker)
{
if (s_watchDirChange)
{
return;
}
s_watchDirChange = true;
Task.Run(async () =>
{
s_logger.Info("=== start new generation ==");
await Task.Delay(200);
lock (s_watchLocker)
{
s_watchDirChange = false;
GenOnce(options, profile);
}
s_logger.Info("=== watch changes ==");
});
}
}
private static int GenOnce(CommandLineOptions options, ProfileTimer profile)
{
int exitCode; int exitCode;
try try
{ {
profile.StartPhase("connect server");
var conn = GenClient.Start(options.Host, options.Port, ProtocolStub.Factories);
profile.StartPhase("load cache meta file"); profile.StartPhase("load cache meta file");
CacheMetaManager.Ins.Load(options.CacheMetaInfoFile); CacheMetaManager.Ins.Load(options.CacheMetaInfoFile);
profile.EndPhaseAndLog(); profile.EndPhaseAndLog();
profile.StartPhase("connect server");
var conn = GenClient.Ins.Start(options.Host, options.Port, ProtocolStub.Factories);
conn.Wait(); conn.Wait();
profile.EndPhaseAndLog(); profile.EndPhaseAndLog();
@ -163,9 +242,13 @@ Options:
exitCode = 1; exitCode = 1;
s_logger.Error(e); s_logger.Error(e);
} }
finally
{
GenClient.Stop();
}
CacheMetaManager.Ins.Save(); CacheMetaManager.Ins.Save();
profile.EndPhaseAndLog(); CacheMetaManager.Ins.Reset();
if (exitCode == 0) if (exitCode == 0)
{ {
s_logger.Info("== succ =="); s_logger.Info("== succ ==");
@ -174,7 +257,7 @@ Options:
{ {
s_logger.Error("== fail =="); s_logger.Error("== fail ==");
} }
Environment.Exit(exitCode); return exitCode;
} }
const int GEN_JOB_TIMEOUT = 120; const int GEN_JOB_TIMEOUT = 120;

View File

@ -121,6 +121,15 @@ namespace Luban.Client.Common.Utils
s_logger.Info("[Save] meta file:{metaFile} updated!", _metaFile); s_logger.Info("[Save] meta file:{metaFile} updated!", _metaFile);
} }
public void Reset()
{
lock (_lock)
{
_dirty = false;
_cacheFileMetas.Clear();
}
}
private MetaInfo GetMetaInfo(string file) private MetaInfo GetMetaInfo(string file)
{ {
lock (_lock) lock (_lock)