Skip to content

Commit

Permalink
Merge pull request #244 from opentween/fix-timeline-scheduler
Browse files Browse the repository at this point in the history
タイムライン更新が停止する不具合への暫定的な対処
  • Loading branch information
upsilon authored Nov 13, 2023
2 parents d92e431 + e6099ad commit c7abf27
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 8 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
更新履歴

==== Unreleased
* CHG: タイムライン更新が停止する不具合が報告される件への暫定的な対処
- タイムライン更新に30秒以上掛かっている場合は完了を待機せず次のタイマーを開始させる
- タイムライン更新の次回実行が1時間以上先になる場合は異常値としてタイマーをリセットする
* FIX: 動画のサムネイル表示時に再生可能であることを示すアイコンが表示されない不具合を修正

==== Ver 3.7.1(2023/07/20)
Expand Down
44 changes: 36 additions & 8 deletions OpenTween/TimelineScheduler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,26 @@ public void RefreshSchedule()
return; // TimerCallback 内で更新されるのでここは単に無視してよい

if (this.Enabled)
this.timer.Change(this.NextTimerDelay(), Timeout.InfiniteTimeSpan);
{
var delay = this.NextTimerDelay();

// タイマーの待機時間が 1 時間を超える値になった場合は異常値として強制的にリセットする
// (タイムライン更新が停止する不具合が報告される件への暫定的な対処)
if (delay >= TimeSpan.FromHours(1))
{
MyCommon.ExceptionOut(new Exception("タイムライン更新の待機時間が異常値のためリセットします: " + delay));
foreach (var key in this.LastUpdatedAt.Keys)
this.LastUpdatedAt[key] = DateTimeUtc.MinValue;

delay = TimeSpan.FromSeconds(10);
}

this.timer.Change(delay, Timeout.InfiniteTimeSpan);
}
else
{
this.timer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
}
}

public void SystemResumed()
Expand Down Expand Up @@ -135,12 +152,22 @@ private async Task TimerCallback()
{
this.preventTimerUpdate = true;

var updateTasks = this.systemResumeMode
var (taskTypes, updateTasks) = this.systemResumeMode
? this.TimerCallback_AfterSystemResume()
: this.TimerCallback_Normal();

await updateTasks.RunAll(runOnThreadPool: true)
.ConfigureAwait(false);
var updateTask = updateTasks.RunAll(runOnThreadPool: true);

// すべてのコールバック関数の Task が完了してから次のタイマーの待機時間を計算する
// ただし、30 秒を超過した場合はエラー報告のダイアログを表示した上で完了を待たずにタイマーを再開する
// (タイムライン更新が停止する不具合が報告される件への暫定的な対処)
var timeout = Task.Delay(TimeSpan.FromSeconds(30));
if (await Task.WhenAny(updateTask, timeout) == timeout)
{
var message = "タイムライン更新が規定時間内に完了しませんでした: " +
string.Join(", ", taskTypes);
throw new Exception(message);
}
}
finally
{
Expand All @@ -149,7 +176,7 @@ await updateTasks.RunAll(runOnThreadPool: true)
}
}

private TaskCollection TimerCallback_Normal()
private (TimelineSchedulerTaskType[] TaskTypes, TaskCollection Task) TimerCallback_Normal()
{
var now = DateTimeUtc.Now;
var round = TimeSpan.FromSeconds(1); // 1秒未満の差異であればまとめて実行する
Expand All @@ -162,16 +189,17 @@ private TaskCollection TimerCallback_Normal()
tasks.Add(taskType);
}

return this.RunUpdateTasks(tasks, now);
return (tasks.ToArray(), this.RunUpdateTasks(tasks, now));
}

private TaskCollection TimerCallback_AfterSystemResume()
private (TimelineSchedulerTaskType[] TaskTypes, TaskCollection Task) TimerCallback_AfterSystemResume()
{
// systemResumeMode では一定期間経過後に全てのタイムラインを更新する
var now = DateTimeUtc.Now;

this.systemResumeMode = false;
return this.RunUpdateTasks(TimelineScheduler.AllTaskTypes, now);
var taskTypes = TimelineScheduler.AllTaskTypes;
return (taskTypes, this.RunUpdateTasks(taskTypes, now));
}

private TaskCollection RunUpdateTasks(IEnumerable<TimelineSchedulerTaskType> taskTypes, DateTimeUtc now)
Expand Down

0 comments on commit c7abf27

Please sign in to comment.