Skip to content
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

Automatically refresh used tab when log file changes #1042

Merged
merged 7 commits into from
Aug 17, 2019

Conversation

thailyn
Copy link
Contributor

@thailyn thailyn commented Jun 22, 2019

This PR accomplishes two things:

  1. Add a class that monitors the client log file for changes, and reads new content when it has. When it finds log messages indicating the player's character has changed locations, it triggers an event.
  2. Add a handler for this event that refreshes all the user's used tabs. This only happens at most ever two minutes.

Both of these behaviors are disabled by default. The former is disabled when the config value ClientLogFileLocation, which should point to the log file, is missing or empty; or if the config value EnableClientLogFileMonitoring is missing or false. The latter is disabled when the config value EnableTabRefreshOnLocationChanged is missing or false.

thailyn added 5 commits June 21, 2019 20:22
Right now, this ClientLogFileWatcher both listens for file changes and
reads the file on a tight schedule, in order to minimize the amount of
time between the file being updated and Procurement seeing it.  Using a
FileSystemWatcher is, unfortunately, not sufficient, since this
generally misses the updates PoE makes to the file.

Currently the only log message that is searched for is for when the user
changes areas.  The file watcher then triggers an event, which can be
listened for by other parts of Procurement.
When the ClientLogFileWatcher detects the log file has been updated and
triggers an event, the StashViewModel will now listen for that event and
trigger updating all used tabs.
Check that the config value "EnableTabRefreshOnLocationChanged" is true
before adding the event listener for the config file changes, which
performs the automatic tab refresh.
@thailyn thailyn marked this pull request as ready for review June 22, 2019 01:02
Copy link
Contributor

@aydjay aydjay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great addition, one of two little nudges and this will be a great addition to procurement.


namespace Procurement.Utility
{
public class ClientLogFileEventArgs : EventArgs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this class into a seperate file

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}
}

protected static System.IO.FileSystemWatcher FileWatcher
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

System.IO is in the includes and the fully qualified path shouldn't be specified, this goes for the rest of the file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I have a bad habit of doing this.


protected void Initialize()
{
if (!Settings.UserSettings.Keys.Contains("ClientLogFileLocation"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this magic string into a constant and update usage online 84

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


internal void Start()
{
if (!Settings.UserSettings.Keys.Contains("EnableClientLogFileMonitoring"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment, move key to a constant

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


PollingTimer = new System.Timers.Timer();
PollingTimer.Elapsed += (s, e) => { ReadClientLogFile(); };
PollingTimer.Interval = 30000; // 30 seconds
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Magic int. Constant needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

if (string.IsNullOrWhiteSpace(fullFilePath))
return;

FileWatcher = new System.IO.FileSystemWatcher();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appreciate that all this code runs "Once" but just incase, null check the setup of both the FileWatcher here and the polling timer. If it does manage to hit the initialize method again it will leak the event handlers you are assigning.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

PollingTimer.Start();
}

internal void Stop()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsubscribe your event handlers to prevent memory leaks,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For which event? PollingTimer.Elapsed? That object's lifetime is the same as the ConfigLogFileWatcher, so, as I understand it, they will both be destructed together, avoiding any memory leaks.

FileWatcher.Changed += OnFileChanged;

PollingTimer = new System.Timers.Timer();
PollingTimer.Elapsed += (s, e) => { ReadClientLogFile(); };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having an anonymous signature like this means you will be unable to unsubscribe from the event later on.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per my other comment, I think this is ok, since the subscriber and publisher's lifetimes are the same, and does not need to be unsubscribed. Please correct me if I am wrong.

@@ -185,6 +185,8 @@ public void Login(bool offline)

ApplicationState.SetDefaults();

ClientLogFileWatcher.Instance.Start();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have called start, but I can't see where you are calling stop. Is there an appropriate place to call stop?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is being called when logging in, and we don't have a concept of logging out (that would be nice), I don't know of a good place to call Stop.

@@ -153,6 +179,16 @@ public StashViewModel(StashView stashView)
currencyDistributionUsesCount = true;
else
configuredOrbType = (OrbType)Enum.Parse(typeof(OrbType), currencyDistributionMetric);

if (Settings.UserSettings.Keys.Contains("EnableTabRefreshOnLocationChanged"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Magic string on the key

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@thailyn thailyn force-pushed the log-file-monitor branch from 8355e09 to c942d6f Compare June 22, 2019 16:12
Copy link
Contributor

@aydjay aydjay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appreciate that there isn't a reasonable place for the "Stop" code, just good for it too be there for completeness. When I mean event handlers i mean anything on the right hand side of "+="

@Stickymaddness Stickymaddness merged commit 3cc6fe0 into Procurement-PoE:master Aug 17, 2019
@thailyn thailyn deleted the log-file-monitor branch October 5, 2019 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants