diff --git a/BirthdayBot/BackgroundServiceRunner.vb b/BirthdayBot/BackgroundServiceRunner.vb
index f132c07..42240ae 100644
--- a/BirthdayBot/BackgroundServiceRunner.vb
+++ b/BirthdayBot/BackgroundServiceRunner.vb
@@ -4,24 +4,24 @@
''' Handles the execution of periodic background tasks.
'''
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 WorkerCancel As New CancellationTokenSource
+ Friend ReadOnly Property BirthdayUpdater As BirthdayRoleUpdate
Private _workerTask As Task
- Private _tickCount As Integer
Sub New(instance As BirthdayBot)
+ BirthdayUpdater = New BirthdayRoleUpdate(instance)
Workers = New List(Of BackgroundService) From {
{New GuildStatistics(instance)},
{New Heartbeat(instance)},
- {New BirthdayRoleUpdate(instance)}
+ {BirthdayUpdater}
}
End Sub
Public Sub Start()
- _tickCount = 0
_workerTask = Task.Factory.StartNew(AddressOf WorkerLoop, WorkerCancel.Token,
TaskCreationOptions.LongRunning, TaskScheduler.Default)
End Sub
@@ -43,7 +43,7 @@ Class BackgroundServiceRunner
' Execute background tasks.
Dim tasks As New List(Of Task)
For Each service In Workers
- tasks.Add(service.OnTick(_tickCount))
+ tasks.Add(service.OnTick())
Next
Await Task.WhenAll(tasks)
Catch ex As TaskCanceledException
@@ -52,7 +52,6 @@ Class BackgroundServiceRunner
Log("Background task", "Unhandled exception in background task thread:")
Log("Background task", ex.ToString())
End Try
- _tickCount += 1
End While
End Function
End Class
diff --git a/BirthdayBot/BackgroundServices/BackgroundService.vb b/BirthdayBot/BackgroundServices/BackgroundService.vb
index 86ab79f..9c44048 100644
--- a/BirthdayBot/BackgroundServices/BackgroundService.vb
+++ b/BirthdayBot/BackgroundServices/BackgroundService.vb
@@ -13,5 +13,5 @@ MustInherit Class BackgroundService
Program.Log(Me.GetType().Name, message)
End Sub
- MustOverride Function OnTick(tick As Integer) As Task
+ MustOverride Function OnTick() As Task
End Class
diff --git a/BirthdayBot/BackgroundServices/BirthdayRoleUpdate.vb b/BirthdayBot/BackgroundServices/BirthdayRoleUpdate.vb
index 0d0acc1..8d718c4 100644
--- a/BirthdayBot/BackgroundServices/BirthdayRoleUpdate.vb
+++ b/BirthdayBot/BackgroundServices/BirthdayRoleUpdate.vb
@@ -4,22 +4,20 @@ Imports Discord.WebSocket
Imports NodaTime
'''
-''' Periodically scans all known guilds and adjusts birthday role membership as necessary.
-''' Also handles birthday announcements.
+''' Core automatic functionality of the bot. Manages role memberships based on birthday information,
+''' and optionally sends the announcement message to appropriate guilds.
'''
Class BirthdayRoleUpdate
Inherits BackgroundService
- Private ReadOnly Property Clock As IClock
Public Sub New(instance As BirthdayBot)
MyBase.New(instance)
- Clock = SystemClock.Instance ' can be replaced with FakeClock during testing
End Sub
'''
- ''' Initial processing: Sets up a task per guild and waits on all.
+ ''' Does processing on all available guilds at once.
'''
- 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))
For Each guild In BotInstance.DiscordClient.Guilds
Dim t = ProcessGuildAsync(guild)
@@ -38,19 +36,24 @@ Class BirthdayRoleUpdate
Next
End Try
- ' Usage report: Show how many announcements were done
- 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).")
+ ' TODO metrics for role sets, unsets, announcements - and how to do that for singles too?
End Function
- Async Function ProcessGuildAsync(guild As SocketGuild) As Task(Of Integer)
+ '''
+ ''' Does role and announcement processing for a single specified guild.
+ '''
+ 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
Dim tz As String
Dim users As IEnumerable(Of GuildUserSettings)
@@ -156,7 +159,7 @@ Class BirthdayRoleUpdate
Dim targetMonth = item.BirthMonth
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
If targetMonth = 2 And targetDay = 29 And Not Date.IsLeapYear(checkNow.Year) Then
targetMonth = 3
diff --git a/BirthdayBot/BackgroundServices/GuildStatistics.vb b/BirthdayBot/BackgroundServices/GuildStatistics.vb
index 82233b8..6679176 100644
--- a/BirthdayBot/BackgroundServices/GuildStatistics.vb
+++ b/BirthdayBot/BackgroundServices/GuildStatistics.vb
@@ -10,10 +10,7 @@ Class GuildStatistics
DBotsToken = instance.Config.DBotsToken
End Sub
- Public Overrides Async Function OnTick(tick As Integer) As Task
- ' Activate roughly every 2 hours (interval: 45)
- If tick Mod 160 <> 2 Then Return
-
+ Public Overrides Async Function OnTick() As Task
Dim count = BotInstance.DiscordClient.Guilds.Count
Log($"Currently in {count} guild(s).")
diff --git a/BirthdayBot/BackgroundServices/Heartbeat.vb b/BirthdayBot/BackgroundServices/Heartbeat.vb
index 15eba4b..db06770 100644
--- a/BirthdayBot/BackgroundServices/Heartbeat.vb
+++ b/BirthdayBot/BackgroundServices/Heartbeat.vb
@@ -1,5 +1,5 @@
'''
-''' Basic heartbeat function - indicates that the background task is still functioning.
+''' Basic heartbeat function - hints that the background task is still alive.
'''
Class Heartbeat
Inherits BackgroundService
@@ -8,19 +8,16 @@ Class Heartbeat
MyBase.New(instance)
End Sub
- Public Overrides Function OnTick(tick As Integer) As Task
- ' Print a message roughly every 15 minutes (assuming 45s per tick).
- If tick Mod 20 = 0 Then
- Dim uptime = DateTimeOffset.UtcNow - Program.BotStartTime
- Log($"Tick {tick:00000} - Bot uptime: {BotUptime()}")
- End If
+ Public Overrides Function OnTick() As Task
+ Dim uptime = DateTimeOffset.UtcNow - Program.BotStartTime
+ Log($"Bot uptime: {BotUptime()}")
' Disconnection warn
For Each shard In BotInstance.DiscordClient.Shards
If shard.ConnectionState = Discord.ConnectionState.Disconnected Then
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.
- ' 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
Next
diff --git a/BirthdayBot/BirthdayBot.vb b/BirthdayBot/BirthdayBot.vb
index 5d9f7ed..330ce79 100644
--- a/BirthdayBot/BirthdayBot.vb
+++ b/BirthdayBot/BirthdayBot.vb
@@ -118,6 +118,7 @@ Class BirthdayBot
End If
End If
+ ' Execute the command
Try
Log("Command", $"{channel.Guild.Name}/{author.Username}#{author.Discriminator}: {msg.Content}")
Await command(csplit, channel, author)
@@ -130,6 +131,9 @@ Class BirthdayBot
' Fail silently.
End Try
End Try
+
+ ' Immediately check for role updates in the invoking guild
+ Await _worker.BirthdayUpdater.SingleUpdateFor(channel.Guild)
End If
End If
End Function
diff --git a/BirthdayBot/BirthdayBot.vbproj b/BirthdayBot/BirthdayBot.vbproj
index 410e126..93b9408 100644
--- a/BirthdayBot/BirthdayBot.vbproj
+++ b/BirthdayBot/BirthdayBot.vbproj
@@ -4,7 +4,7 @@
Exe
BirthdayBot
netcoreapp2.0
- 1.3.3
+ 1.3.4
Noi
Discord bot for birthday reminders.