Skip to content

Modified monitor to be able to accept and pass along options to threads #131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/Reddit.NET/Controllers/Comment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1259,7 +1259,7 @@ public bool MonitorCommentScore(int? monitoringDelayMs = null, int? monitoringBa
}

string key = "CommentScore";
return Monitor(key, new Thread(() => MonitorCommentScoreThread(key, monitoringDelayMs)), Id);
return Monitor(key, new ThreadWrapper(new Thread(() => MonitorCommentScoreThread(key, monitoringDelayMs))), Id);
}

/// <summary>
Expand All @@ -1283,15 +1283,19 @@ private void MonitorCommentScoreThread(string key, int? monitoringDelayMs = null
/// <param name="subKey">Monitoring subKey</param>
/// <param name="startDelayMs">How long to wait before starting the thread in milliseconds (default: 0)</param>
/// <param name="monitoringDelayMs">How long to wait between monitoring queries; pass null to leave it auto-managed (default: null)</param>
/// <param name="options">The implementation-specific options</param>
/// <returns>The newly-created monitoring thread.</returns>
protected override Thread CreateMonitoringThread(string key, string subKey, int startDelayMs = 0, int? monitoringDelayMs = null)
protected override ThreadWrapper CreateMonitoringThread(string key, string subKey, int startDelayMs = 0,
int? monitoringDelayMs = null, object options = null)
{
switch (key)
{
default:
throw new RedditControllerException("Unrecognized key : " + key + ".");
case "CommentScore":
return new Thread(() => MonitorComment(key, "score", subKey, startDelayMs, monitoringDelayMs));
return new ThreadWrapper(new Thread(() =>
MonitorComment(key, "score", subKey, startDelayMs, monitoringDelayMs)),
options);
}
}

Expand Down
363 changes: 300 additions & 63 deletions src/Reddit.NET/Controllers/Comments.cs

Large diffs are not rendered by default.

52 changes: 34 additions & 18 deletions src/Reddit.NET/Controllers/Internal/Monitors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Reddit.Exceptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace Reddit.Controllers.Internal
Expand All @@ -10,7 +11,7 @@ public abstract class Monitors : BaseController
{
public int MonitoringWaitDelayMS = 1500;

internal Dictionary<string, Thread> Threads;
internal Dictionary<string, ThreadWrapper> Threads;

protected volatile bool Terminate = false;

Expand All @@ -29,22 +30,22 @@ public abstract class Monitors : BaseController

public Monitors() : base()
{
Threads = new Dictionary<string, Thread>();
Threads = new Dictionary<string, ThreadWrapper>();
BreakOnFailure = false;
MonitoringSchedule = new List<MonitoringSchedule> { null }; // Monitor 24/7 by default. --Kris
}

protected bool Monitor(string key, Thread thread, string subKey)
protected bool Monitor(string key, ThreadWrapper thread, string subKey)
{
bool res = Monitor(key, thread, subKey, out Thread newThread);
bool res = Monitor(key, thread, subKey, out ThreadWrapper newThread);

RebuildThreads(subKey);
LaunchThreadIfNotNull(key, newThread);

return res;
}

internal bool Monitor(string key, Thread thread, string subKey, out Thread newThread)
internal bool Monitor(string key, ThreadWrapper thread, string subKey, out ThreadWrapper newThread)
{
newThread = null;
if (IsMonitored(key, subKey))
Expand Down Expand Up @@ -116,25 +117,31 @@ public bool IsScheduled()
// TODO - Preserve custom thread monitoring delays when they're rebuilt (occurs whenever a new monitoring thread starts or an existing one stops). --Kris
protected void RebuildThreads(string subKey)
{
List<string> oldThreads = new List<string>(Threads.Keys);
ResetThreads(oldThreads);
List<(string key, object options)> oldThreads =
Threads.Select(t => new {t.Key, t.Value.Options})
.AsEnumerable()
.Select(t => (t.Key, t.Options))
.ToList();
List<string> oldThreadKeys = oldThreads.Select(o => o.key).ToList();

ResetThreads(oldThreadKeys);

int i = 0;
foreach (string key in oldThreads)
foreach ((string key, object options) in oldThreads)
{
Threads.Add(key, CreateMonitoringThread(key, subKey, (i * MonitoringWaitDelayMS)));
Threads[key].Start();
Threads.Add(key, CreateMonitoringThread(key, subKey, (i * MonitoringWaitDelayMS), options: options));
Threads[key].Thread.Start();
i++;
}
}

protected void LaunchThreadIfNotNull(string key, Thread thread)
protected void LaunchThreadIfNotNull(string key, ThreadWrapper thread)
{
if (thread != null)
{
Threads.Add(key, thread);
Threads[key].Start();
while (!Threads[key].IsAlive) { }
Threads[key].Thread.Start();
while (!Threads[key].Thread.IsAlive) { }
}
}

Expand All @@ -152,10 +159,10 @@ public void WaitOrDie(string key, int timeout = 60)
{
if (Threads.ContainsKey(key))
{
Thread thread = Threads[key];
ThreadWrapper thread = Threads[key];

KillThread(key);
WaitOrDie(thread, timeout);
WaitOrDie(thread.Thread, timeout);
}
}

Expand Down Expand Up @@ -183,14 +190,14 @@ protected void KillThread(Thread thread)

protected void KillThread(string key)
{
KillThread(Threads[key]);
KillThread(Threads[key].Thread);

Threads.Remove(key);
}

public void KillAllMonitoringThreads()
{
foreach (KeyValuePair<string, Thread> pair in Threads)
foreach (KeyValuePair<string, ThreadWrapper> pair in Threads)
{
KillThread(pair.Key);
}
Expand Down Expand Up @@ -229,6 +236,15 @@ internal void InitMonitoringCache(bool useCache, string type)
}
}

protected abstract Thread CreateMonitoringThread(string key, string subKey, int startDelayMs = 0, int? monitoringDelayMs = null);
/// <summary>
/// Creates a new monitoring thread.
/// </summary>
/// <param name="key">Monitoring key</param>
/// <param name="subKey">Monitoring subKey</param>
/// <param name="startDelayMs">How long to wait before starting the thread in milliseconds (default: 0)</param>
/// <param name="monitoringDelayMs">How long to wait between monitoring queries; pass null to leave it auto-managed (default: null)</param>
/// <param name="options">Implementation-specific options.</param>
/// <returns>The newly-created monitoring thread.</returns>
protected abstract ThreadWrapper CreateMonitoringThread(string key, string subKey, int startDelayMs = 0, int? monitoringDelayMs = null, object options = null);
}
}
32 changes: 32 additions & 0 deletions src/Reddit.NET/Controllers/Internal/ThreadWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// TedCruzResponderBot - Simple real-time chat application.
// Copyright (C) 2021 Jerrett D. Davis
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

using System.Threading;

namespace Reddit.Controllers.Internal
{
public class ThreadWrapper
{
public ThreadWrapper(Thread thread, object options = null)
{
Thread = thread;
Options = options;
}

public Thread Thread { get; }
public object Options { get; }
}
}
24 changes: 17 additions & 7 deletions src/Reddit.NET/Controllers/LiveThread.cs
Original file line number Diff line number Diff line change
Expand Up @@ -912,7 +912,7 @@ public bool MonitorThread(int? monitoringDelayMs = null, int? monitoringBaseDela
InitMonitoringCache(useCache, "thread");

string key = "LiveThread";
return Monitor(key, new Thread(() => MonitorThreadThread(key, monitoringDelayMs)), Id);
return Monitor(key, new ThreadWrapper(new Thread(() => MonitorThreadThread(key, monitoringDelayMs))), Id);
}

/// <summary>
Expand Down Expand Up @@ -951,7 +951,7 @@ public bool MonitorContributors(int? monitoringDelayMs = null, int? monitoringBa
InitMonitoringCache(useCache, "contributors");

string key = "LiveThreadContributors";
return Monitor(key, new Thread(() => MonitorContributorsThread(key, monitoringDelayMs)), Id);
return Monitor(key, new ThreadWrapper(new Thread(() => MonitorContributorsThread(key, monitoringDelayMs))), Id);
}

/// <summary>
Expand Down Expand Up @@ -990,7 +990,7 @@ public bool MonitorUpdates(int? monitoringDelayMs = null, int? monitoringBaseDel
InitMonitoringCache(useCache, "updates");

string key = "LiveThreadUpdates";
return Monitor(key, new Thread(() => MonitorUpdatesThread(key, monitoringDelayMs)), Id);
return Monitor(key, new ThreadWrapper(new Thread(() => MonitorUpdatesThread(key, monitoringDelayMs))), Id);
}

public bool LiveThreadIsMonitored()
Expand All @@ -1008,18 +1008,28 @@ public bool LiveThreadUpdatesIsMonitored()
return IsMonitored("LiveThreadUpdates", "updates");
}

protected override Thread CreateMonitoringThread(string key, string subKey, int startDelayMs = 0, int? monitoringDelayMs = null)
/// <summary>
/// Creates a new monitoring thread.
/// </summary>
/// <param name="key">Monitoring key</param>
/// <param name="subKey">Monitoring subKey</param>
/// <param name="startDelayMs">How long to wait before starting the thread in milliseconds (default: 0)</param>
/// <param name="monitoringDelayMs">How long to wait between monitoring queries; pass null to leave it auto-managed (default: null)</param>
/// <param name="options">The implementation-specific options</param>
/// <returns>The newly-created monitoring thread.</returns>
protected override ThreadWrapper CreateMonitoringThread(string key, string subKey, int startDelayMs = 0,
int? monitoringDelayMs = null, object options = null)
{
switch (key)
{
default:
throw new RedditControllerException("Unrecognized key.");
case "LiveThread":
return new Thread(() => MonitorLiveThread(key, "thread", subKey, startDelayMs, monitoringDelayMs));
return new ThreadWrapper(new Thread(() => MonitorLiveThread(key, "thread", subKey, startDelayMs, monitoringDelayMs)));
case "LiveThreadContributors":
return new Thread(() => MonitorLiveThread(key, "contributors", subKey, startDelayMs, monitoringDelayMs));
return new ThreadWrapper(new Thread(() => MonitorLiveThread(key, "contributors", subKey, startDelayMs, monitoringDelayMs)));
case "LiveThreadUpdates":
return new Thread(() => MonitorLiveThread(key, "updates", subKey, startDelayMs, monitoringDelayMs));
return new ThreadWrapper(new Thread(() => MonitorLiveThread(key, "updates", subKey, startDelayMs, monitoringDelayMs)));
}
}

Expand Down
28 changes: 19 additions & 9 deletions src/Reddit.NET/Controllers/Modmail.cs
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,9 @@ public bool MonitorRecent(int? monitoringDelayMs = null, int? monitoringBaseDela
InitMonitoringCache(useCache, "recent");

string key = "ModmailMessagesRecent";
return Monitor(key, new Thread(() => MonitorModmailMessagesThread(recent, key, "recent", monitoringDelayMs: monitoringDelayMs)), "ModmailMessages");
return Monitor(key, new ThreadWrapper(
new Thread(() => MonitorModmailMessagesThread(recent, key, "recent", monitoringDelayMs: monitoringDelayMs)))
, "ModmailMessages");
}

/// <summary>
Expand Down Expand Up @@ -676,7 +678,9 @@ public bool MonitorMod(int? monitoringDelayMs = null, int? monitoringBaseDelayMs
InitMonitoringCache(useCache, "mod");

string key = "ModmailMessagesMod";
return Monitor(key, new Thread(() => MonitorModmailMessagesThread(mod, key, "mod", monitoringDelayMs: monitoringDelayMs)), "ModmailMessages");
return Monitor(key,
new ThreadWrapper(new Thread(() => MonitorModmailMessagesThread(mod, key, "mod", monitoringDelayMs: monitoringDelayMs))),
"ModmailMessages");
}

/// <summary>
Expand Down Expand Up @@ -715,7 +719,9 @@ public bool MonitorUser(int? monitoringDelayMs = null, int? monitoringBaseDelayM
InitMonitoringCache(useCache, "user");

string key = "ModmailMessagesUser";
return Monitor(key, new Thread(() => MonitorModmailMessagesThread(user, key, "user", monitoringDelayMs: monitoringDelayMs)), "ModmailMessages");
return Monitor(key,
new ThreadWrapper(new Thread(() => MonitorModmailMessagesThread(user, key, "user", monitoringDelayMs: monitoringDelayMs))),
"ModmailMessages");
}

/// <summary>
Expand Down Expand Up @@ -754,7 +760,9 @@ public bool MonitorUnread(int? monitoringDelayMs = null, int? monitoringBaseDela
InitMonitoringCache(useCache, "unread");

string key = "ModmailMessagesUnread";
return Monitor(key, new Thread(() => MonitorModmailMessagesThread(unread, key, "unread", monitoringDelayMs: monitoringDelayMs)), "ModmailMessages");
return Monitor(key,
new ThreadWrapper(new Thread(() => MonitorModmailMessagesThread(unread, key, "unread", monitoringDelayMs: monitoringDelayMs))),
"ModmailMessages");
}

/// <summary>
Expand Down Expand Up @@ -992,21 +1000,23 @@ public bool ModmailMessagesUnreadIsMonitored()
/// <param name="subKey">Monitoring subKey</param>
/// <param name="startDelayMs">How long to wait before starting the thread in milliseconds (default: 0)</param>
/// <param name="monitoringDelayMs">How long to wait between monitoring queries; pass null to leave it auto-managed (default: null)</param>
/// <param name="options">The implementation-specific options</param>
/// <returns>The newly-created monitoring thread.</returns>
protected override Thread CreateMonitoringThread(string key, string subKey, int startDelayMs = 0, int? monitoringDelayMs = null)
protected override ThreadWrapper CreateMonitoringThread(string key, string subKey, int startDelayMs = 0,
int? monitoringDelayMs = null, object options = null)
{
switch (key)
{
default:
throw new RedditControllerException("Unrecognized key.");
case "ModmailMessagesRecent":
return new Thread(() => MonitorModmailMessagesThread(recent, key, "recent", startDelayMs, monitoringDelayMs));
return new ThreadWrapper(new Thread(() => MonitorModmailMessagesThread(recent, key, "recent", startDelayMs, monitoringDelayMs)),options);
case "ModmailMessagesMod":
return new Thread(() => MonitorModmailMessagesThread(mod, key, "mod", startDelayMs, monitoringDelayMs));
return new ThreadWrapper(new Thread(() => MonitorModmailMessagesThread(mod, key, "mod", startDelayMs, monitoringDelayMs)),options);
case "ModmailMessagesUser":
return new Thread(() => MonitorModmailMessagesThread(user, key, "user", startDelayMs, monitoringDelayMs));
return new ThreadWrapper(new Thread(() => MonitorModmailMessagesThread(user, key, "user", startDelayMs, monitoringDelayMs)),options);
case "ModmailMessagesUnread":
return new Thread(() => MonitorModmailMessagesThread(unread, key, "unread", startDelayMs, monitoringDelayMs));
return new ThreadWrapper(new Thread(() => MonitorModmailMessagesThread(unread, key, "unread", startDelayMs, monitoringDelayMs)),options);
}
}
}
Expand Down
16 changes: 11 additions & 5 deletions src/Reddit.NET/Controllers/Post.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1305,7 +1305,8 @@ public bool MonitorPostData(int? monitoringDelayMs = null, int? monitoringBaseDe
}

string key = "PostData";
return Monitor(key, new Thread(() => MonitorPostDataThread(key, monitoringDelayMs)), Id);
return Monitor(key, new ThreadWrapper(
new Thread(() => MonitorPostDataThread(key, monitoringDelayMs))), Id);
}

/// <summary>
Expand Down Expand Up @@ -1364,7 +1365,8 @@ public bool MonitorPostScore(int? monitoringDelayMs = null, int? monitoringBaseD
}

string key = "PostScore";
return Monitor(key, new Thread(() => MonitorPostScoreThread(key, monitoringDelayMs)), Id);
return Monitor(key, new ThreadWrapper(
new Thread(() => MonitorPostScoreThread(key, monitoringDelayMs))), Id);
}

/// <summary>
Expand Down Expand Up @@ -1402,17 +1404,21 @@ private void MonitorPostScoreThread(string key, int? monitoringDelayMs = null)
/// <param name="subKey">Monitoring subKey</param>
/// <param name="startDelayMs">How long to wait before starting the thread in milliseconds (default: 0)</param>
/// <param name="monitoringDelayMs">How long to wait between monitoring queries; pass null to leave it auto-managed (default: null)</param>
/// <param name="options">The implementation-specific options</param>
/// <returns>The newly-created monitoring thread.</returns>
protected override Thread CreateMonitoringThread(string key, string subKey, int startDelayMs = 0, int? monitoringDelayMs = null)
protected override ThreadWrapper CreateMonitoringThread(string key, string subKey, int startDelayMs = 0,
int? monitoringDelayMs = null, object options = null)
{
switch (key)
{
default:
throw new RedditControllerException("Unrecognized key : " + key + ".");
case "PostData":
return new Thread(() => MonitorPost(key, "data", subKey, startDelayMs, monitoringDelayMs));
return new ThreadWrapper(
new Thread(() => MonitorPost(key, "data", subKey, startDelayMs, monitoringDelayMs)), options);
case "PostScore":
return new Thread(() => MonitorPost(key, "score", subKey, startDelayMs, monitoringDelayMs));
return new ThreadWrapper(
new Thread(() => MonitorPost(key, "score", subKey, startDelayMs, monitoringDelayMs)), options);
}
}

Expand Down
Loading