Slightly faster startup and database access. Shard 0 will now report total guild count

This commit is contained in:
Master Kwoth 2017-06-22 23:59:54 +02:00
parent bed3001ce1
commit 741538a982
14 changed files with 252 additions and 241 deletions

View File

@ -6,7 +6,7 @@
//using System; //using System;
//using System.Linq; //using System.Linq;
//using System.Threading.Tasks; //using System.Threading.Tasks;
////todo Rewrite
//namespace NadekoBot.Modules.Utility //namespace NadekoBot.Modules.Utility
//{ //{
// public partial class Utility // public partial class Utility

View File

@ -320,10 +320,6 @@ namespace NadekoBot.Modules.Utility
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Stats() public async Task Stats()
{ {
//var shardId = Context.Guild != null
// ? _client.GetShardIdFor(Context.Guild)
// : 0;
await Context.Channel.EmbedAsync( await Context.Channel.EmbedAsync(
new EmbedBuilder().WithOkColor() new EmbedBuilder().WithOkColor()
.WithAuthor(eab => eab.WithName($"NadekoBot v{StatsService.BotVersion}") .WithAuthor(eab => eab.WithName($"NadekoBot v{StatsService.BotVersion}")
@ -339,13 +335,7 @@ namespace NadekoBot.Modules.Utility
.AddField(efb => efb.WithName(GetText("uptime")).WithValue(_stats.GetUptimeString("\n")).WithIsInline(true)) .AddField(efb => efb.WithName(GetText("uptime")).WithValue(_stats.GetUptimeString("\n")).WithIsInline(true))
.AddField(efb => efb.WithName(GetText("presence")).WithValue( .AddField(efb => efb.WithName(GetText("presence")).WithValue(
GetText("presence_txt", GetText("presence_txt",
_client.Guilds.Count, _stats.TextChannels, _stats.VoiceChannels)).WithIsInline(true)) _stats.GuildCount, _stats.TextChannels, _stats.VoiceChannels)).WithIsInline(true)));
#if !GLOBAL_NADEKO
//.WithFooter(efb => efb.WithText(GetText("stats_songs",
// _music.MusicPlayers.Count(mp => mp.Value.CurrentSong != null),
// _music.MusicPlayers.Sum(mp => mp.Value.Playlist.Count))))
#endif
);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]

View File

@ -139,14 +139,16 @@ namespace NadekoBot
private void AddServices() private void AddServices()
{ {
var startingGuildIdList = Client.Guilds.Select(x => (long)x.Id).ToList(); var startingGuildIdList = Client.Guilds.Select(x => (long)x.Id).ToList();
//this unit of work will be used for initialization of all modules too, to prevent multiple queries from running
using (var uow = Db.UnitOfWork) using (var uow = Db.UnitOfWork)
{ {
AllGuildConfigs = uow.GuildConfigs.GetAllGuildConfigs(startingGuildIdList).ToImmutableArray(); AllGuildConfigs = uow.GuildConfigs.GetAllGuildConfigs(startingGuildIdList).ToImmutableArray();
}
Localization = new Localization(BotConfig.Locale, AllGuildConfigs.ToDictionary(x => x.GuildId, x => x.Locale), Db); Localization = new Localization(BotConfig.Locale, AllGuildConfigs.ToDictionary(x => x.GuildId, x => x.Locale), Db);
Strings = new NadekoStrings(Localization); Strings = new NadekoStrings(Localization);
CommandHandler = new CommandHandler(Client, Db, BotConfig, AllGuildConfigs, CommandService, Credentials, this); CommandHandler = new CommandHandler(Client, Db, BotConfig, AllGuildConfigs, CommandService, Credentials, this);
Stats = new StatsService(Client, CommandHandler, Credentials); Stats = new StatsService(Client, CommandHandler, Credentials, ShardCoord);
var soundcloudApiService = new SoundCloudApiService(Credentials); var soundcloudApiService = new SoundCloudApiService(Credentials);
@ -157,7 +159,7 @@ namespace NadekoBot
//module services //module services
//todo 90 - autodiscover, DI, and add instead of manual like this //todo 90 - autodiscover, DI, and add instead of manual like this
#region utility #region utility
var remindService = new RemindService(Client, BotConfig, Db, startingGuildIdList); var remindService = new RemindService(Client, BotConfig, Db, startingGuildIdList, uow);
var repeaterService = new MessageRepeaterService(this, Client, AllGuildConfigs); var repeaterService = new MessageRepeaterService(this, Client, AllGuildConfigs);
//var converterService = new ConverterService(Db); //var converterService = new ConverterService(Db);
var commandMapService = new CommandMapService(AllGuildConfigs); var commandMapService = new CommandMapService(AllGuildConfigs);
@ -180,9 +182,9 @@ namespace NadekoBot
var animeSearchService = new AnimeSearchService(); var animeSearchService = new AnimeSearchService();
#endregion #endregion
var clashService = new ClashOfClansService(Client, Db, Localization, Strings); var clashService = new ClashOfClansService(Client, Db, Localization, Strings, uow, startingGuildIdList);
var musicService = new MusicService(GoogleApi, Strings, Localization, Db, soundcloudApiService, Credentials, AllGuildConfigs); var musicService = new MusicService(GoogleApi, Strings, Localization, Db, soundcloudApiService, Credentials, AllGuildConfigs);
var crService = new CustomReactionsService(permissionsService, Db, Client, CommandHandler, BotConfig); var crService = new CustomReactionsService(permissionsService, Db, Client, CommandHandler, BotConfig, uow);
#region Games #region Games
var gamesService = new GamesService(Client, BotConfig, AllGuildConfigs, Strings, Images, CommandHandler); var gamesService = new GamesService(Client, BotConfig, AllGuildConfigs, Strings, Images, CommandHandler);
@ -211,6 +213,7 @@ namespace NadekoBot
#endregion #endregion
//initialize Services //initialize Services
Services = new NServiceProvider.ServiceProviderBuilder() Services = new NServiceProvider.ServiceProviderBuilder()
.Add<ILocalization>(Localization) .Add<ILocalization>(Localization)
@ -266,6 +269,7 @@ namespace NadekoBot
.Add<NadekoBot>(this) .Add<NadekoBot>(this)
.Build(); .Build();
CommandHandler.AddServices(Services); CommandHandler.AddServices(Services);
//setup typereaders //setup typereaders
@ -276,32 +280,38 @@ namespace NadekoBot
CommandService.AddTypeReader<ModuleOrCrInfo>(new ModuleOrCrTypeReader(CommandService)); CommandService.AddTypeReader<ModuleOrCrInfo>(new ModuleOrCrTypeReader(CommandService));
CommandService.AddTypeReader<IGuild>(new GuildTypeReader(Client)); CommandService.AddTypeReader<IGuild>(new GuildTypeReader(Client));
CommandService.AddTypeReader<GuildDateTime>(new GuildDateTimeTypeReader(guildTimezoneService)); CommandService.AddTypeReader<GuildDateTime>(new GuildDateTimeTypeReader(guildTimezoneService));
}
} }
private Task LoginAsync(string token) private async Task LoginAsync(string token)
{ {
var clientReady = new TaskCompletionSource<bool>();
Task SetClientReady()
{
clientReady.TrySetResult(true);
return Task.CompletedTask;
}
//connect //connect
try { sem.WaitOne(); } catch (AbandonedMutexException) { } try { sem.WaitOne(); } catch (AbandonedMutexException) { }
_log.Info("Shard {0} logging in ...", ShardId); _log.Info("Shard {0} logging in ...", ShardId);
try try
{ {
Client.LoginAsync(TokenType.Bot, token).GetAwaiter().GetResult(); Client.LoginAsync(TokenType.Bot, token).GetAwaiter().GetResult();
Client.StartAsync().GetAwaiter().GetResult(); Client.StartAsync().GetAwaiter().GetResult();
while (Client.ConnectionState != ConnectionState.Connected) Client.Ready += SetClientReady;
Task.Delay(100).GetAwaiter().GetResult(); await clientReady.Task.ConfigureAwait(false);
Client.Ready -= SetClientReady;
} }
finally finally
{ {
_log.Info("Shard {0} logged in.", ShardId); _log.Info("Shard {0} logged in.", ShardId);
sem.Release(); sem.Release();
} }
return Task.CompletedTask;
//_log.Info("Waiting for all shards to connect...");
//while (!Client.Shards.All(x => x.ConnectionState == ConnectionState.Connected))
//{
// _log.Info("Connecting... {0}/{1}", Client.Shards.Count(x => x.ConnectionState == ConnectionState.Connected), Client.Shards.Count);
// await Task.Delay(1000).ConfigureAwait(false);
//}
} }
public async Task RunAsync(params string[] args) public async Task RunAsync(params string[] args)

View File

@ -39,12 +39,8 @@ namespace NadekoBot.Services.Administration
_client = client; _client = client;
_creds = creds; _creds = creds;
using (var uow = _db.UnitOfWork) ForwardDMs = bc.ForwardMessages;
{ ForwardDMsToAllOwners = bc.ForwardToAllOwners;
var config = uow.BotConfig.GetOrCreate();
ForwardDMs = config.ForwardMessages;
ForwardDMsToAllOwners = config.ForwardToAllOwners;
}
var _ = Task.Run(async () => var _ = Task.Run(async () =>
{ {

View File

@ -1,6 +1,7 @@
using Discord; using Discord;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
@ -25,18 +26,18 @@ namespace NadekoBot.Services.ClashOfClans
public ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; } public ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; }
public ClashOfClansService(DiscordSocketClient client, DbService db, ILocalization localization, NadekoStrings strings) public ClashOfClansService(DiscordSocketClient client, DbService db,
ILocalization localization, NadekoStrings strings, IUnitOfWork uow,
List<long> guilds)
{ {
_client = client; _client = client;
_db = db; _db = db;
_localization = localization; _localization = localization;
_strings = strings; _strings = strings;
using (var uow = _db.UnitOfWork)
{
ClashWars = new ConcurrentDictionary<ulong, List<ClashWar>>( ClashWars = new ConcurrentDictionary<ulong, List<ClashWar>>(
uow.ClashOfClans uow.ClashOfClans
.GetAllWars() .GetAllWars(guilds)
.Select(cw => .Select(cw =>
{ {
cw.Channel = _client.GetGuild(cw.GuildId)? cw.Channel = _client.GetGuild(cw.GuildId)?
@ -46,7 +47,6 @@ namespace NadekoBot.Services.ClashOfClans
.Where(cw => cw.Channel != null) .Where(cw => cw.Channel != null)
.GroupBy(cw => cw.GuildId) .GroupBy(cw => cw.GuildId)
.ToDictionary(g => g.Key, g => g.ToList())); .ToDictionary(g => g.Key, g => g.ToList()));
}
checkWarTimer = new Timer(async _ => checkWarTimer = new Timer(async _ =>
{ {

View File

@ -10,6 +10,7 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Services.Permissions; using NadekoBot.Services.Permissions;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services.Database;
namespace NadekoBot.Services.CustomReactions namespace NadekoBot.Services.CustomReactions
{ {
@ -28,7 +29,7 @@ namespace NadekoBot.Services.CustomReactions
private readonly BotConfig _bc; private readonly BotConfig _bc;
public CustomReactionsService(PermissionService perms, DbService db, public CustomReactionsService(PermissionService perms, DbService db,
DiscordSocketClient client, CommandHandler cmd, BotConfig bc) DiscordSocketClient client, CommandHandler cmd, BotConfig bc, IUnitOfWork uow)
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
_db = db; _db = db;
@ -37,13 +38,10 @@ namespace NadekoBot.Services.CustomReactions
_cmd = cmd; _cmd = cmd;
_bc = bc; _bc = bc;
using (var uow = _db.UnitOfWork)
{
var items = uow.CustomReactions.GetAll(); var items = uow.CustomReactions.GetAll();
GuildReactions = new ConcurrentDictionary<ulong, CustomReaction[]>(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => g.ToArray())); GuildReactions = new ConcurrentDictionary<ulong, CustomReaction[]>(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => g.ToArray()));
GlobalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray(); GlobalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray();
} }
}
public void ClearStats() => ReactionStats.Clear(); public void ClearStats() => ReactionStats.Clear();

View File

@ -5,6 +5,6 @@ namespace NadekoBot.Services.Database.Repositories
{ {
public interface IClashOfClansRepository : IRepository<ClashWar> public interface IClashOfClansRepository : IRepository<ClashWar>
{ {
IEnumerable<ClashWar> GetAllWars(); IEnumerable<ClashWar> GetAllWars(List<long> guilds);
} }
} }

View File

@ -11,9 +11,11 @@ namespace NadekoBot.Services.Database.Repositories.Impl
{ {
} }
public IEnumerable<ClashWar> GetAllWars() public IEnumerable<ClashWar> GetAllWars(List<long> guilds)
{ {
var toReturn = _set.Include(cw => cw.Bases) var toReturn = _set
.Where(cw => guilds.Contains((long)cw.GuildId))
.Include(cw => cw.Bases)
.ToList(); .ToList();
toReturn.ForEach(cw => cw.Bases = cw.Bases.Where(w => w.SequenceNumber != null).OrderBy(w => w.SequenceNumber).ToList()); toReturn.ForEach(cw => cw.Bases = cw.Bases.Where(w => w.SequenceNumber != null).OrderBy(w => w.SequenceNumber).ToList());
return toReturn; return toReturn;

View File

@ -13,6 +13,7 @@ namespace NadekoBot.Services
double MessagesPerSecond { get; } double MessagesPerSecond { get; }
long TextChannels { get; } long TextChannels { get; }
long VoiceChannels { get; } long VoiceChannels { get; }
int GuildCount { get; }
TimeSpan GetUptime(); TimeSpan GetUptime();
string GetUptimeString(string separator = ", "); string GetUptimeString(string separator = ", ");

View File

@ -35,11 +35,16 @@ namespace NadekoBot.Services.Impl
public long CommandsRan => Interlocked.Read(ref _commandsRan); public long CommandsRan => Interlocked.Read(ref _commandsRan);
private readonly Timer _carbonitexTimer; private readonly Timer _carbonitexTimer;
private readonly ShardsCoordinator _sc;
public StatsService(DiscordSocketClient client, CommandHandler cmdHandler, IBotCredentials creds) public int GuildCount =>
_sc?.GuildCount ?? _client.Guilds.Count();
public StatsService(DiscordSocketClient client, CommandHandler cmdHandler, IBotCredentials creds, ShardsCoordinator sc)
{ {
_client = client; _client = client;
_creds = creds; _creds = creds;
_sc = sc;
_started = DateTime.UtcNow; _started = DateTime.UtcNow;
_client.MessageReceived += _ => Task.FromResult(Interlocked.Increment(ref _messageCounter)); _client.MessageReceived += _ => Task.FromResult(Interlocked.Increment(ref _messageCounter));
@ -122,31 +127,34 @@ namespace NadekoBot.Services.Impl
}; };
//todo carbonitex update //todo carbonitex update
//_carbonitexTimer = new Timer(async (state) => if (sc != null)
//{ {
// if (string.IsNullOrWhiteSpace(_creds.CarbonKey)) _carbonitexTimer = new Timer(async (state) =>
// return; {
// try if (string.IsNullOrWhiteSpace(_creds.CarbonKey))
// { return;
// using (var http = new HttpClient()) try
// { {
// using (var content = new FormUrlEncodedContent( using (var http = new HttpClient())
// new Dictionary<string, string> { {
// { "servercount", _client.Guilds.Count.ToString() }, using (var content = new FormUrlEncodedContent(
// { "key", _creds.CarbonKey }})) new Dictionary<string, string> {
// { { "servercount", sc.GuildCount.ToString() },
// content.Headers.Clear(); { "key", _creds.CarbonKey }}))
// content.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); {
content.Headers.Clear();
content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
// await http.PostAsync("https://www.carbonitex.net/discord/data/botdata.php", content).ConfigureAwait(false); await http.PostAsync("https://www.carbonitex.net/discord/data/botdata.php", content).ConfigureAwait(false);
// } }
// } }
// } }
// catch catch
// { {
// // ignored // ignored
// } }
//}, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1)); }, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
}
} }
public void Initialize() public void Initialize()

View File

@ -11,6 +11,7 @@ using System.Threading.Tasks;
using Discord; using Discord;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services;
namespace NadekoBot.Services.Permissions namespace NadekoBot.Services.Permissions
{ {
@ -31,13 +32,12 @@ namespace NadekoBot.Services.Permissions
_cmd = cmd; _cmd = cmd;
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
if (client.ShardId == 0)
TryMigratePermissions(bc); TryMigratePermissions(bc);
client.Ready += delegate
{
using (var uow = _db.UnitOfWork) using (var uow = _db.UnitOfWork)
{ {
foreach (var x in uow.GuildConfigs.Permissionsv2ForAll(client.Guilds.Select(x => (long)x.Id).ToList())) foreach (var x in uow.GuildConfigs.Permissionsv2ForAll(client.Guilds.ToArray().Select(x => (long)x.Id).ToList()))
{ {
Cache.TryAdd(x.GuildId, new PermissionCache() Cache.TryAdd(x.GuildId, new PermissionCache()
{ {
@ -47,8 +47,6 @@ namespace NadekoBot.Services.Permissions
}); });
} }
} }
return Task.CompletedTask;
};
sw.Stop(); sw.Stop();
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s"); _log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
@ -74,10 +72,9 @@ namespace NadekoBot.Services.Permissions
private void TryMigratePermissions(BotConfig bc) private void TryMigratePermissions(BotConfig bc)
{ {
var log = LogManager.GetCurrentClassLogger(); var log = LogManager.GetCurrentClassLogger();
using (var uow = _db.UnitOfWork) if (bc.PermissionVersion <= 1)
{ {
var _bc = uow.BotConfig.GetOrCreate(); using (var uow = _db.UnitOfWork)
if (_bc.PermissionVersion <= 1)
{ {
log.Info("Permission version is 1, upgrading to 2."); log.Info("Permission version is 1, upgrading to 2.");
var oldCache = new ConcurrentDictionary<ulong, OldPermissionCache>(uow.GuildConfigs var oldCache = new ConcurrentDictionary<ulong, OldPermissionCache>(uow.GuildConfigs
@ -132,9 +129,13 @@ namespace NadekoBot.Services.Permissions
log.Info("Permission migration to v2 is done."); log.Info("Permission migration to v2 is done.");
} }
_bc.PermissionVersion = 2; bc.PermissionVersion = 2;
uow.Complete();
} }
if (_bc.PermissionVersion <= 2) }
if (bc.PermissionVersion <= 2)
{
using (var uow = _db.UnitOfWork)
{ {
var oldPrefixes = new[] { ".", ";", "!!", "!m", "!", "+", "-", "$", ">" }; var oldPrefixes = new[] { ".", ";", "!!", "!m", "!", "+", "-", "$", ">" };
uow._context.Database.ExecuteSqlCommand( uow._context.Database.ExecuteSqlCommand(
@ -150,11 +151,11 @@ WHERE secondaryTargetName LIKE '.%' OR
secondaryTargetName LIKE '>%' OR secondaryTargetName LIKE '>%' OR
secondaryTargetName LIKE '-%' OR secondaryTargetName LIKE '-%' OR
secondaryTargetName LIKE '!%';"); secondaryTargetName LIKE '!%';");
_bc.PermissionVersion = 3; bc.PermissionVersion = 3;
}
uow.Complete(); uow.Complete();
} }
} }
}
public async Task AddPermissions(ulong guildId, params Permissionv2[] perms) public async Task AddPermissions(ulong guildId, params Permissionv2[] perms)
{ {

View File

@ -1,6 +1,8 @@
using Discord; using Discord;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
@ -73,7 +75,7 @@ namespace NadekoBot.Services.Searches
})); }));
firstStreamNotifPass = false; firstStreamNotifPass = false;
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(60)); }, null, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(60));
} }
public async Task<StreamStatus> GetStreamStatus(FollowedStream stream, bool checkCache = true) public async Task<StreamStatus> GetStreamStatus(FollowedStream stream, bool checkCache = true)

View File

@ -1,6 +1,7 @@
using Discord; using Discord;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using NLog; using NLog;
using System; using System;
@ -33,7 +34,8 @@ namespace NadekoBot.Services.Utility
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
private readonly DbService _db; private readonly DbService _db;
public RemindService(DiscordSocketClient client, BotConfig config, DbService db, List<long> guilds) public RemindService(DiscordSocketClient client, BotConfig config, DbService db,
List<long> guilds, IUnitOfWork uow)
{ {
_config = config; _config = config;
_client = client; _client = client;
@ -42,11 +44,8 @@ namespace NadekoBot.Services.Utility
cancelSource = new CancellationTokenSource(); cancelSource = new CancellationTokenSource();
cancelAllToken = cancelSource.Token; cancelAllToken = cancelSource.Token;
List<Reminder> reminders;
using (var uow = _db.UnitOfWork) var reminders = uow.Reminders.GetIncludedReminders(guilds).ToList();
{
reminders = uow.Reminders.GetIncludedReminders(guilds).ToList();
}
RemindMessageFormat = _config.RemindMessageFormat; RemindMessageFormat = _config.RemindMessageFormat;
foreach (var r in reminders) foreach (var r in reminders)

View File

@ -14,6 +14,10 @@ namespace NadekoBot
private readonly BotCredentials Credentials; private readonly BotCredentials Credentials;
private Process[] ShardProcesses; private Process[] ShardProcesses;
public ShardComMessage[] Statuses { get; } public ShardComMessage[] Statuses { get; }
public int GuildCount => Statuses.ToArray()
.Where(x => x != null)
.Sum(x => x.Guilds);
private readonly Logger _log; private readonly Logger _log;
private readonly ShardComServer _comServer; private readonly ShardComServer _comServer;