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.Linq;
//using System.Threading.Tasks;
////todo Rewrite
//namespace NadekoBot.Modules.Utility
//{
// public partial class Utility

View File

@ -320,10 +320,6 @@ namespace NadekoBot.Modules.Utility
[NadekoCommand, Usage, Description, Aliases]
public async Task Stats()
{
//var shardId = Context.Guild != null
// ? _client.GetShardIdFor(Context.Guild)
// : 0;
await Context.Channel.EmbedAsync(
new EmbedBuilder().WithOkColor()
.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("presence")).WithValue(
GetText("presence_txt",
_client.Guilds.Count, _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
);
_stats.GuildCount, _stats.TextChannels, _stats.VoiceChannels)).WithIsInline(true)));
}
[NadekoCommand, Usage, Description, Aliases]

View File

@ -139,14 +139,16 @@ namespace NadekoBot
private void AddServices()
{
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)
{
AllGuildConfigs = uow.GuildConfigs.GetAllGuildConfigs(startingGuildIdList).ToImmutableArray();
}
Localization = new Localization(BotConfig.Locale, AllGuildConfigs.ToDictionary(x => x.GuildId, x => x.Locale), Db);
Strings = new NadekoStrings(Localization);
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);
@ -157,7 +159,7 @@ namespace NadekoBot
//module services
//todo 90 - autodiscover, DI, and add instead of manual like this
#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 converterService = new ConverterService(Db);
var commandMapService = new CommandMapService(AllGuildConfigs);
@ -180,9 +182,9 @@ namespace NadekoBot
var animeSearchService = new AnimeSearchService();
#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 crService = new CustomReactionsService(permissionsService, Db, Client, CommandHandler, BotConfig);
var crService = new CustomReactionsService(permissionsService, Db, Client, CommandHandler, BotConfig, uow);
#region Games
var gamesService = new GamesService(Client, BotConfig, AllGuildConfigs, Strings, Images, CommandHandler);
@ -211,6 +213,7 @@ namespace NadekoBot
#endregion
//initialize Services
Services = new NServiceProvider.ServiceProviderBuilder()
.Add<ILocalization>(Localization)
@ -266,6 +269,7 @@ namespace NadekoBot
.Add<NadekoBot>(this)
.Build();
CommandHandler.AddServices(Services);
//setup typereaders
@ -276,32 +280,38 @@ namespace NadekoBot
CommandService.AddTypeReader<ModuleOrCrInfo>(new ModuleOrCrTypeReader(CommandService));
CommandService.AddTypeReader<IGuild>(new GuildTypeReader(Client));
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
try { sem.WaitOne(); } catch (AbandonedMutexException) { }
_log.Info("Shard {0} logging in ...", ShardId);
try
{
Client.LoginAsync(TokenType.Bot, token).GetAwaiter().GetResult();
Client.StartAsync().GetAwaiter().GetResult();
while (Client.ConnectionState != ConnectionState.Connected)
Task.Delay(100).GetAwaiter().GetResult();
Client.Ready += SetClientReady;
await clientReady.Task.ConfigureAwait(false);
Client.Ready -= SetClientReady;
}
finally
{
_log.Info("Shard {0} logged in.", ShardId);
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)

View File

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

View File

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

View File

@ -10,6 +10,7 @@ using System;
using System.Threading.Tasks;
using NadekoBot.Services.Permissions;
using NadekoBot.Extensions;
using NadekoBot.Services.Database;
namespace NadekoBot.Services.CustomReactions
{
@ -28,7 +29,7 @@ namespace NadekoBot.Services.CustomReactions
private readonly BotConfig _bc;
public CustomReactionsService(PermissionService perms, DbService db,
DiscordSocketClient client, CommandHandler cmd, BotConfig bc)
DiscordSocketClient client, CommandHandler cmd, BotConfig bc, IUnitOfWork uow)
{
_log = LogManager.GetCurrentClassLogger();
_db = db;
@ -37,13 +38,10 @@ namespace NadekoBot.Services.CustomReactions
_cmd = cmd;
_bc = bc;
using (var uow = _db.UnitOfWork)
{
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()));
GlobalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray();
}
}
public void ClearStats() => ReactionStats.Clear();

View File

@ -5,6 +5,6 @@ namespace NadekoBot.Services.Database.Repositories
{
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();
toReturn.ForEach(cw => cw.Bases = cw.Bases.Where(w => w.SequenceNumber != null).OrderBy(w => w.SequenceNumber).ToList());
return toReturn;

View File

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

View File

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

View File

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

View File

@ -1,6 +1,8 @@
using Discord;
using Discord.WebSocket;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Models;
using Newtonsoft.Json;
using System;
@ -73,7 +75,7 @@ namespace NadekoBot.Services.Searches
}));
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)

View File

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

View File

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