mirror of
https://github.com/NoiTheCat/BirthdayBot.git
synced 2024-11-21 21:54:36 +00:00
Change frequency of automatic birthday role checks
Changed up how the background services behave. Removed tick count, greatly increased the interval, and added a manual call to update individual guilds as their information changes. Further changes to this may be made in the near future, going as far as to possibly remvoe this structure altogether.
This commit is contained in:
parent
8ca06279e9
commit
b31813c210
7 changed files with 38 additions and 38 deletions
|
@ -4,24 +4,24 @@
|
||||||
''' Handles the execution of periodic background tasks.
|
''' Handles the execution of periodic background tasks.
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Class BackgroundServiceRunner
|
Class BackgroundServiceRunner
|
||||||
Const Interval = 45 ' Tick interval in seconds. Adjust as needed.
|
Const Interval = 8 * 60 ' Tick interval in seconds. Adjust as needed.
|
||||||
|
|
||||||
Private ReadOnly Property Workers As List(Of BackgroundService)
|
Private ReadOnly Property Workers As List(Of BackgroundService)
|
||||||
Private ReadOnly Property WorkerCancel As New CancellationTokenSource
|
Private ReadOnly Property WorkerCancel As New CancellationTokenSource
|
||||||
|
Friend ReadOnly Property BirthdayUpdater As BirthdayRoleUpdate
|
||||||
|
|
||||||
Private _workerTask As Task
|
Private _workerTask As Task
|
||||||
Private _tickCount As Integer
|
|
||||||
|
|
||||||
Sub New(instance As BirthdayBot)
|
Sub New(instance As BirthdayBot)
|
||||||
|
BirthdayUpdater = New BirthdayRoleUpdate(instance)
|
||||||
Workers = New List(Of BackgroundService) From {
|
Workers = New List(Of BackgroundService) From {
|
||||||
{New GuildStatistics(instance)},
|
{New GuildStatistics(instance)},
|
||||||
{New Heartbeat(instance)},
|
{New Heartbeat(instance)},
|
||||||
{New BirthdayRoleUpdate(instance)}
|
{BirthdayUpdater}
|
||||||
}
|
}
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Public Sub Start()
|
Public Sub Start()
|
||||||
_tickCount = 0
|
|
||||||
_workerTask = Task.Factory.StartNew(AddressOf WorkerLoop, WorkerCancel.Token,
|
_workerTask = Task.Factory.StartNew(AddressOf WorkerLoop, WorkerCancel.Token,
|
||||||
TaskCreationOptions.LongRunning, TaskScheduler.Default)
|
TaskCreationOptions.LongRunning, TaskScheduler.Default)
|
||||||
End Sub
|
End Sub
|
||||||
|
@ -43,7 +43,7 @@ Class BackgroundServiceRunner
|
||||||
' Execute background tasks.
|
' Execute background tasks.
|
||||||
Dim tasks As New List(Of Task)
|
Dim tasks As New List(Of Task)
|
||||||
For Each service In Workers
|
For Each service In Workers
|
||||||
tasks.Add(service.OnTick(_tickCount))
|
tasks.Add(service.OnTick())
|
||||||
Next
|
Next
|
||||||
Await Task.WhenAll(tasks)
|
Await Task.WhenAll(tasks)
|
||||||
Catch ex As TaskCanceledException
|
Catch ex As TaskCanceledException
|
||||||
|
@ -52,7 +52,6 @@ Class BackgroundServiceRunner
|
||||||
Log("Background task", "Unhandled exception in background task thread:")
|
Log("Background task", "Unhandled exception in background task thread:")
|
||||||
Log("Background task", ex.ToString())
|
Log("Background task", ex.ToString())
|
||||||
End Try
|
End Try
|
||||||
_tickCount += 1
|
|
||||||
End While
|
End While
|
||||||
End Function
|
End Function
|
||||||
End Class
|
End Class
|
||||||
|
|
|
@ -13,5 +13,5 @@ MustInherit Class BackgroundService
|
||||||
Program.Log(Me.GetType().Name, message)
|
Program.Log(Me.GetType().Name, message)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
MustOverride Function OnTick(tick As Integer) As Task
|
MustOverride Function OnTick() As Task
|
||||||
End Class
|
End Class
|
||||||
|
|
|
@ -4,22 +4,20 @@ Imports Discord.WebSocket
|
||||||
Imports NodaTime
|
Imports NodaTime
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' Periodically scans all known guilds and adjusts birthday role membership as necessary.
|
''' Core automatic functionality of the bot. Manages role memberships based on birthday information,
|
||||||
''' Also handles birthday announcements.
|
''' and optionally sends the announcement message to appropriate guilds.
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Class BirthdayRoleUpdate
|
Class BirthdayRoleUpdate
|
||||||
Inherits BackgroundService
|
Inherits BackgroundService
|
||||||
Private ReadOnly Property Clock As IClock
|
|
||||||
|
|
||||||
Public Sub New(instance As BirthdayBot)
|
Public Sub New(instance As BirthdayBot)
|
||||||
MyBase.New(instance)
|
MyBase.New(instance)
|
||||||
Clock = SystemClock.Instance ' can be replaced with FakeClock during testing
|
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' Initial processing: Sets up a task per guild and waits on all.
|
''' Does processing on all available guilds at once.
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Public Overrides Async Function OnTick(tick As Integer) As Task
|
Public Overrides Async Function OnTick() As Task
|
||||||
Dim tasks As New List(Of Task(Of Integer))
|
Dim tasks As New List(Of Task(Of Integer))
|
||||||
For Each guild In BotInstance.DiscordClient.Guilds
|
For Each guild In BotInstance.DiscordClient.Guilds
|
||||||
Dim t = ProcessGuildAsync(guild)
|
Dim t = ProcessGuildAsync(guild)
|
||||||
|
@ -38,19 +36,24 @@ Class BirthdayRoleUpdate
|
||||||
Next
|
Next
|
||||||
End Try
|
End Try
|
||||||
|
|
||||||
' Usage report: Show how many announcements were done
|
' TODO metrics for role sets, unsets, announcements - and how to do that for singles too?
|
||||||
Dim announces = 0
|
|
||||||
Dim guilds = 0
|
|
||||||
For Each task In tasks
|
|
||||||
If task.Result > 0 Then
|
|
||||||
announces += task.Result
|
|
||||||
guilds += 1
|
|
||||||
End If
|
|
||||||
Next
|
|
||||||
If announces > 0 Then Log($"Announcing {announces} birthday(s) in {guilds} guild(s).")
|
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Async Function ProcessGuildAsync(guild As SocketGuild) As Task(Of Integer)
|
''' <summary>
|
||||||
|
''' Does role and announcement processing for a single specified guild.
|
||||||
|
''' </summary>
|
||||||
|
Public Async Function SingleUpdateFor(guild As SocketGuild) As Task
|
||||||
|
Try
|
||||||
|
Await ProcessGuildAsync(guild)
|
||||||
|
Catch ex As Exception
|
||||||
|
Log("Encountered an error during guild processing:")
|
||||||
|
Log(ex.ToString())
|
||||||
|
End Try
|
||||||
|
|
||||||
|
' TODO metrics for role sets, unsets, announcements - and I mentioned this above too
|
||||||
|
End Function
|
||||||
|
|
||||||
|
Private Async Function ProcessGuildAsync(guild As SocketGuild) As Task(Of Integer)
|
||||||
' Gather required information
|
' Gather required information
|
||||||
Dim tz As String
|
Dim tz As String
|
||||||
Dim users As IEnumerable(Of GuildUserSettings)
|
Dim users As IEnumerable(Of GuildUserSettings)
|
||||||
|
@ -156,7 +159,7 @@ Class BirthdayRoleUpdate
|
||||||
Dim targetMonth = item.BirthMonth
|
Dim targetMonth = item.BirthMonth
|
||||||
Dim targetDay = item.BirthDay
|
Dim targetDay = item.BirthDay
|
||||||
|
|
||||||
Dim checkNow = Clock.GetCurrentInstant().InZone(tz)
|
Dim checkNow = SystemClock.Instance.GetCurrentInstant().InZone(tz)
|
||||||
' Special case: If birthday is February 29 and it's not a leap year, recognize it on March 1st
|
' Special case: If birthday is February 29 and it's not a leap year, recognize it on March 1st
|
||||||
If targetMonth = 2 And targetDay = 29 And Not Date.IsLeapYear(checkNow.Year) Then
|
If targetMonth = 2 And targetDay = 29 And Not Date.IsLeapYear(checkNow.Year) Then
|
||||||
targetMonth = 3
|
targetMonth = 3
|
||||||
|
|
|
@ -10,10 +10,7 @@ Class GuildStatistics
|
||||||
DBotsToken = instance.Config.DBotsToken
|
DBotsToken = instance.Config.DBotsToken
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Public Overrides Async Function OnTick(tick As Integer) As Task
|
Public Overrides Async Function OnTick() As Task
|
||||||
' Activate roughly every 2 hours (interval: 45)
|
|
||||||
If tick Mod 160 <> 2 Then Return
|
|
||||||
|
|
||||||
Dim count = BotInstance.DiscordClient.Guilds.Count
|
Dim count = BotInstance.DiscordClient.Guilds.Count
|
||||||
Log($"Currently in {count} guild(s).")
|
Log($"Currently in {count} guild(s).")
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' Basic heartbeat function - indicates that the background task is still functioning.
|
''' Basic heartbeat function - hints that the background task is still alive.
|
||||||
''' </summary>
|
''' </summary>
|
||||||
Class Heartbeat
|
Class Heartbeat
|
||||||
Inherits BackgroundService
|
Inherits BackgroundService
|
||||||
|
@ -8,19 +8,16 @@ Class Heartbeat
|
||||||
MyBase.New(instance)
|
MyBase.New(instance)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Public Overrides Function OnTick(tick As Integer) As Task
|
Public Overrides Function OnTick() As Task
|
||||||
' Print a message roughly every 15 minutes (assuming 45s per tick).
|
Dim uptime = DateTimeOffset.UtcNow - Program.BotStartTime
|
||||||
If tick Mod 20 = 0 Then
|
Log($"Bot uptime: {BotUptime()}")
|
||||||
Dim uptime = DateTimeOffset.UtcNow - Program.BotStartTime
|
|
||||||
Log($"Tick {tick:00000} - Bot uptime: {BotUptime()}")
|
|
||||||
End If
|
|
||||||
|
|
||||||
' Disconnection warn
|
' Disconnection warn
|
||||||
For Each shard In BotInstance.DiscordClient.Shards
|
For Each shard In BotInstance.DiscordClient.Shards
|
||||||
If shard.ConnectionState = Discord.ConnectionState.Disconnected Then
|
If shard.ConnectionState = Discord.ConnectionState.Disconnected Then
|
||||||
Log($"Shard {shard.ShardId} is disconnected! Restart the app if this persists.")
|
Log($"Shard {shard.ShardId} is disconnected! Restart the app if this persists.")
|
||||||
' The library alone cannot be restarted as it is in an unknown state. It was not designed to be restarted.
|
' The library alone cannot be restarted as it is in an unknown state. It was not designed to be restarted.
|
||||||
' This is the part where we'd signal something to restart us if we were fancy.
|
' TODO This is the part where we'd signal something to restart us if we were fancy.
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,7 @@ Class BirthdayBot
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
|
' Execute the command
|
||||||
Try
|
Try
|
||||||
Log("Command", $"{channel.Guild.Name}/{author.Username}#{author.Discriminator}: {msg.Content}")
|
Log("Command", $"{channel.Guild.Name}/{author.Username}#{author.Discriminator}: {msg.Content}")
|
||||||
Await command(csplit, channel, author)
|
Await command(csplit, channel, author)
|
||||||
|
@ -130,6 +131,9 @@ Class BirthdayBot
|
||||||
' Fail silently.
|
' Fail silently.
|
||||||
End Try
|
End Try
|
||||||
End Try
|
End Try
|
||||||
|
|
||||||
|
' Immediately check for role updates in the invoking guild
|
||||||
|
Await _worker.BirthdayUpdater.SingleUpdateFor(channel.Guild)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RootNamespace>BirthdayBot</RootNamespace>
|
<RootNamespace>BirthdayBot</RootNamespace>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
<Version>1.3.3</Version>
|
<Version>1.3.4</Version>
|
||||||
<Authors>Noi</Authors>
|
<Authors>Noi</Authors>
|
||||||
<Company />
|
<Company />
|
||||||
<Description>Discord bot for birthday reminders.</Description>
|
<Description>Discord bot for birthday reminders.</Description>
|
||||||
|
|
Loading…
Reference in a new issue