using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
{
public class TimelineScheduler
{
- private readonly Timer timer;
+ private readonly AsyncTimer timer;
private bool enabled = false;
private bool systemResumeMode = false;
public TimeSpan UpdateIntervalConfig { get; set; } = Timeout.InfiniteTimeSpan;
public TimeSpan UpdateAfterSystemResume { get; set; } = Timeout.InfiniteTimeSpan;
+ public bool EnableUpdateHome
+ => this.UpdateIntervalHome != Timeout.InfiniteTimeSpan;
+
+ public bool EnableUpdateMention
+ => this.UpdateIntervalMention != Timeout.InfiniteTimeSpan;
+
+ public bool EnableUpdateDm
+ => this.UpdateIntervalDm != Timeout.InfiniteTimeSpan;
+
+ public bool EnableUpdatePublicSearch
+ => this.UpdateIntervalPublicSearch != Timeout.InfiniteTimeSpan;
+
+ public bool EnableUpdateUser
+ => this.UpdateIntervalUser != Timeout.InfiniteTimeSpan;
+
+ public bool EnableUpdateList
+ => this.UpdateIntervalList != Timeout.InfiniteTimeSpan;
+
+ public bool EnableUpdateConfig
+ => this.UpdateIntervalConfig != Timeout.InfiniteTimeSpan;
+
+ public bool EnableUpdateSystemResume
+ => this.UpdateAfterSystemResume != Timeout.InfiniteTimeSpan;
+
public Func<Task>? UpdateHome;
public Func<Task>? UpdateMention;
public Func<Task>? UpdateDm;
}
public TimelineScheduler()
- => this.timer = new Timer(_ => this.TimerCallback());
+ => this.timer = new AsyncTimer(this.TimerCallback);
public void RefreshSchedule()
{
public void SystemResumed()
{
+ if (!this.EnableUpdateSystemResume)
+ return;
+
this.SystemResumedAt = DateTimeUtc.Now;
this.systemResumeMode = true;
this.RefreshSchedule();
}
- private async void TimerCallback()
+ private async Task TimerCallback()
{
try
{
var round = TimeSpan.FromSeconds(1); // 1秒未満の差異であればまとめて実行する
var tasks = UpdateTask.None;
- var nextScheduledHome = this.LastUpdateHome + this.UpdateIntervalHome;
- if (nextScheduledHome - now < round)
- tasks |= UpdateTask.Home;
+ if (this.EnableUpdateHome)
+ {
+ var nextScheduledHome = this.LastUpdateHome + this.UpdateIntervalHome;
+ if (nextScheduledHome - now < round)
+ tasks |= UpdateTask.Home;
+ }
- var nextScheduledMention = this.LastUpdateMention + this.UpdateIntervalMention;
- if (nextScheduledMention - now < round)
- tasks |= UpdateTask.Mention;
+ if (this.EnableUpdateMention)
+ {
+ var nextScheduledMention = this.LastUpdateMention + this.UpdateIntervalMention;
+ if (nextScheduledMention - now < round)
+ tasks |= UpdateTask.Mention;
+ }
- var nextScheduledDm = this.LastUpdateDm + this.UpdateIntervalDm;
- if (nextScheduledDm - now < round)
- tasks |= UpdateTask.Dm;
+ if (this.EnableUpdateDm)
+ {
+ var nextScheduledDm = this.LastUpdateDm + this.UpdateIntervalDm;
+ if (nextScheduledDm - now < round)
+ tasks |= UpdateTask.Dm;
+ }
- var nextScheduledPublicSearch = this.LastUpdatePublicSearch + this.UpdateIntervalPublicSearch;
- if (nextScheduledPublicSearch - now < round)
- tasks |= UpdateTask.PublicSearch;
+ if (this.EnableUpdatePublicSearch)
+ {
+ var nextScheduledPublicSearch = this.LastUpdatePublicSearch + this.UpdateIntervalPublicSearch;
+ if (nextScheduledPublicSearch - now < round)
+ tasks |= UpdateTask.PublicSearch;
+ }
- var nextScheduledUser = this.LastUpdateUser + this.UpdateIntervalUser;
- if (nextScheduledUser - now < round)
- tasks |= UpdateTask.User;
+ if (this.EnableUpdateUser)
+ {
+ var nextScheduledUser = this.LastUpdateUser + this.UpdateIntervalUser;
+ if (nextScheduledUser - now < round)
+ tasks |= UpdateTask.User;
+ }
- var nextScheduledList = this.LastUpdateList + this.UpdateIntervalList;
- if (nextScheduledList - now < round)
- tasks |= UpdateTask.List;
+ if (this.EnableUpdateList)
+ {
+ var nextScheduledList = this.LastUpdateList + this.UpdateIntervalList;
+ if (nextScheduledList - now < round)
+ tasks |= UpdateTask.List;
+ }
- var nextScheduledConfig = this.LastUpdateConfig + this.UpdateIntervalConfig;
- if (nextScheduledConfig - now < round)
- tasks |= UpdateTask.Config;
+ if (this.EnableUpdateConfig)
+ {
+ var nextScheduledConfig = this.LastUpdateConfig + this.UpdateIntervalConfig;
+ if (nextScheduledConfig - now < round)
+ tasks |= UpdateTask.Config;
+ }
await this.RunUpdateTasks(tasks, now).ConfigureAwait(false);
}
private async Task RunUpdateTasks(UpdateTask tasks, DateTimeUtc now)
{
- var updateTasks = new List<Task>(capacity: 7);
-
- // LastUpdate* を次の時刻に更新してから Update* を実行すること
- // (LastUpdate* が更新されずに Update* が例外を投げると無限ループに陥る)
+ var updateTasks = new List<Func<Task>>(capacity: 7);
if ((tasks & UpdateTask.Home) == UpdateTask.Home)
{
this.LastUpdateHome = now;
if (this.UpdateHome != null)
- updateTasks.Add(this.UpdateHome());
+ updateTasks.Add(this.UpdateHome);
}
if ((tasks & UpdateTask.Mention) == UpdateTask.Mention)
{
this.LastUpdateMention = now;
if (this.UpdateMention != null)
- updateTasks.Add(this.UpdateMention());
+ updateTasks.Add(this.UpdateMention);
}
if ((tasks & UpdateTask.Dm) == UpdateTask.Dm)
{
this.LastUpdateDm = now;
if (this.UpdateDm != null)
- updateTasks.Add(this.UpdateDm());
+ updateTasks.Add(this.UpdateDm);
}
if ((tasks & UpdateTask.PublicSearch) == UpdateTask.PublicSearch)
{
this.LastUpdatePublicSearch = now;
if (this.UpdatePublicSearch != null)
- updateTasks.Add(this.UpdatePublicSearch());
+ updateTasks.Add(this.UpdatePublicSearch);
}
if ((tasks & UpdateTask.User) == UpdateTask.User)
{
this.LastUpdateUser = now;
if (this.UpdateUser != null)
- updateTasks.Add(this.UpdateUser());
+ updateTasks.Add(this.UpdateUser);
}
if ((tasks & UpdateTask.List) == UpdateTask.List)
{
this.LastUpdateList = now;
if (this.UpdateList != null)
- updateTasks.Add(this.UpdateList());
+ updateTasks.Add(this.UpdateList);
}
if ((tasks & UpdateTask.Config) == UpdateTask.Config)
{
this.LastUpdateConfig = now;
if (this.UpdateConfig != null)
- updateTasks.Add(this.UpdateConfig());
+ updateTasks.Add(this.UpdateConfig);
}
- await Task.WhenAll(updateTasks).ConfigureAwait(false);
+ await Task.WhenAll(updateTasks.Select(x => Task.Run(x)))
+ .ConfigureAwait(false);
}
private TimeSpan NextTimerDelay()
// 次に更新が予定される時刻を判定する
var min = DateTimeUtc.MaxValue;
- var nextScheduledHome = this.LastUpdateHome + this.UpdateIntervalHome;
- if (nextScheduledHome < min)
- min = nextScheduledHome;
+ if (this.EnableUpdateHome)
+ {
+ var nextScheduledHome = this.LastUpdateHome + this.UpdateIntervalHome;
+ if (nextScheduledHome < min)
+ min = nextScheduledHome;
+ }
- var nextScheduledMention = this.LastUpdateMention + this.UpdateIntervalMention;
- if (nextScheduledMention < min)
- min = nextScheduledMention;
+ if (this.EnableUpdateMention)
+ {
+ var nextScheduledMention = this.LastUpdateMention + this.UpdateIntervalMention;
+ if (nextScheduledMention < min)
+ min = nextScheduledMention;
+ }
- var nextScheduledDm = this.LastUpdateDm + this.UpdateIntervalDm;
- if (nextScheduledDm < min)
- min = nextScheduledDm;
+ if (this.EnableUpdateDm)
+ {
+ var nextScheduledDm = this.LastUpdateDm + this.UpdateIntervalDm;
+ if (nextScheduledDm < min)
+ min = nextScheduledDm;
+ }
- var nextScheduledPublicSearch = this.LastUpdatePublicSearch + this.UpdateIntervalPublicSearch;
- if (nextScheduledPublicSearch < min)
- min = nextScheduledPublicSearch;
+ if (this.EnableUpdatePublicSearch)
+ {
+ var nextScheduledPublicSearch = this.LastUpdatePublicSearch + this.UpdateIntervalPublicSearch;
+ if (nextScheduledPublicSearch < min)
+ min = nextScheduledPublicSearch;
+ }
- var nextScheduledUser = this.LastUpdateUser + this.UpdateIntervalUser;
- if (nextScheduledUser < min)
- min = nextScheduledUser;
+ if (this.EnableUpdateUser)
+ {
+ var nextScheduledUser = this.LastUpdateUser + this.UpdateIntervalUser;
+ if (nextScheduledUser < min)
+ min = nextScheduledUser;
+ }
- var nextScheduledList = this.LastUpdateList + this.UpdateIntervalList;
- if (nextScheduledList < min)
- min = nextScheduledList;
+ if (this.EnableUpdateList)
+ {
+ var nextScheduledList = this.LastUpdateList + this.UpdateIntervalList;
+ if (nextScheduledList < min)
+ min = nextScheduledList;
+ }
- var nextScheduledConfig = this.LastUpdateConfig + this.UpdateIntervalConfig;
- if (nextScheduledConfig < min)
- min = nextScheduledConfig;
+ if (this.EnableUpdateConfig)
+ {
+ var nextScheduledConfig = this.LastUpdateConfig + this.UpdateIntervalConfig;
+ if (nextScheduledConfig < min)
+ min = nextScheduledConfig;
+ }
delay = min - DateTimeUtc.Now;