using Core.Annotations; using Core.DI; using Core.Models.Enums; using Core.Models.Spt.Config; using Core.Models.Utils; using Core.Servers; using Core.Services; namespace Core.Utils; [Injectable(InjectionType.Singleton)] public class App { protected Dictionary _onUpdateLastRun; protected CoreConfig _coreConfig; private ISptLogger _logger; private TimeUtil _timeUtil; private LocalisationService _localisationService; private ConfigServer _configServer; private EncodingUtil _encodingUtil; private HttpServer _httpServer; private DatabaseService _databaseService; private IEnumerable _onLoad; private IEnumerable _onUpdate; public App( ISptLogger logger, TimeUtil timeUtil, LocalisationService localisationService, ConfigServer configServer, EncodingUtil encodingUtil, HttpServer httpServer, DatabaseService databaseService, IEnumerable onLoadComponents, IEnumerable onUpdateComponents ) { _logger = logger; _timeUtil = timeUtil; _localisationService = localisationService; _configServer = configServer; _encodingUtil = encodingUtil; _httpServer = httpServer; _databaseService = databaseService; _onLoad = onLoadComponents; _onUpdate = onUpdateComponents; _coreConfig = configServer.GetConfig(); } public async Task Run() { // execute onLoad callbacks _logger.Info(_localisationService.GetText("executing_startup_callbacks")); _logger.Debug($"OS: {Environment.OSVersion.Version} | {Environment.OSVersion.Platform}"); //_logger.Debug($"CPU: {ApplicationId.ProcessorArchitecture} cores: {os.cpus().length}"); //_logger.Debug($"RAM: {(os.totalmem() / 1024 / 1024 / 1024).toFixed(2)}GB"); //_logger.Debug($"PATH: {this.encodingUtil.toBase64(process.argv[0])}"); //_logger.Debug($"PATH: {this.encodingUtil.toBase64(process.execPath)}"); //_logger.Debug($"Server: {ProgramStatics.SPT_VERSION || _coreConfig.SptVersion}"); //if (ProgramStatics.BUILD_TIME) { // _logger.Debug($"Date: {ProgramStatics.BUILD_TIME}"); //} //if (ProgramStatics.COMMIT) { // _logger.Debug($"Commit: {ProgramStatics.COMMIT}"); //} foreach (var onLoad in _onLoad) await onLoad.OnLoad(); new Timer(_ => Update(_onUpdate), null, TimeSpan.Zero, TimeSpan.FromMilliseconds(5000)); } protected async Task Update(IEnumerable onUpdateComponents) { // If the server has failed to start, skip any update calls if (!_httpServer.IsStarted() || !_databaseService.IsDatabaseValid()) return; foreach (var updateable in onUpdateComponents) { var success = false; if (!_onUpdateLastRun.TryGetValue(updateable.GetRoute(), out var lastRunTimeTimestamp)) lastRunTimeTimestamp = 0; var secondsSinceLastRun = _timeUtil.GetTimeStamp() - lastRunTimeTimestamp; try { success = await updateable.OnUpdate(secondsSinceLastRun); } catch (Exception err) { LogUpdateException(err, updateable); } if (success) { _onUpdateLastRun[updateable.GetRoute()] = _timeUtil.GetTimeStamp(); } else { /* temporary for debug */ var warnTime = 20 * 60; if (secondsSinceLastRun % warnTime == 0) _logger.Debug(_localisationService.GetText("route_onupdate_no_response", updateable.GetRoute())); } } } protected void LogUpdateException(Exception err, OnUpdate updateable) { _logger.Error(_localisationService.GetText("scheduled_event_failed_to_run", updateable.GetRoute())); _logger.Error(err.ToString()); } }