Skip to content

Conversation

@tombogle
Copy link
Collaborator

@tombogle tombogle commented Jan 6, 2026

This change is Reviewable

@tombogle tombogle requested a review from andrew-polk January 6, 2026 14:35
@tombogle tombogle self-assigned this Jan 6, 2026
Also, added missing DLL to Installer
Could not load file or assembly 'System.Text.Json, Version=9.0.0.0'
…by tests

Added explicit method to call to report project progress.
Included advances in completed stages in project progress analytics
Copy link
Contributor

@andrew-polk andrew-polk left a comment

Choose a reason for hiding this comment

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

@andrew-polk reviewed 20 files and all commit messages, and made 1 comment.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @tombogle).


src/SayMore/Model/Project.cs line 208 at r1 (raw file):

					if (personDelta > 0)
						properties["PersonsAdded"] = personDelta.ToString();

I guess you don't care about removal of sessions or persons? (assuming that is possible)

Same for media duration below

Deal with race condition to be able to track progress reliably.
Remove unnecessary tracking of intermediate updates.
Copy link
Collaborator Author

@tombogle tombogle left a comment

Choose a reason for hiding this comment

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

@tombogle made 1 comment.
Reviewable status: 15 of 20 files reviewed, 1 unresolved discussion (waiting on @andrew-polk).


src/SayMore/Model/Project.cs line 208 at r1 (raw file):

Previously, andrew-polk wrote…

I guess you don't care about removal of sessions or persons? (assuming that is possible)

Same for media duration below

I'm thinking of "progress" as advancing toward some (nebulous) "completion point." While getting rid of cruft can also be a form of progress, it's not the main focus. There are several other things that I could take into account, such as archiving, but that is already a concretely trackable event. My hope is to have an "event" that more-or-less answers the question, did the user make measurable progress toward creation of a finished work during this SayMore session, as opposed to just going in and poking around.

@andrew-polk
Copy link
Contributor

src/SayMore/Model/Project.cs line 208 at r1 (raw file):

Previously, tombogle (Tom Bogle) wrote…

I'm thinking of "progress" as advancing toward some (nebulous) "completion point." While getting rid of cruft can also be a form of progress, it's not the main focus. There are several other things that I could take into account, such as archiving, but that is already a concretely trackable event. My hope is to have an "event" that more-or-less answers the question, did the user make measurable progress toward creation of a finished work during this SayMore session, as opposed to just going in and poking around.

👍

Copy link
Contributor

@andrew-polk andrew-polk left a comment

Choose a reason for hiding this comment

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

@andrew-polk reviewed 5 files and all commit messages, and made 1 comment.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @tombogle).


src/SayMore/Model/Project.cs line 680 at r2 (raw file):

SetAdditionalMetsData

typo
SetAdditionalMetaData

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Comment on lines +953 to +975
public void TrackStatistics(StatisticsViewModel statisticsViewModel)
{
if (_statisticsViewModel != null)
_statisticsViewModel.FinishedGatheringStatisticsForAllFiles -= FinishedGatheringStatistics;

_statisticsViewModel = statisticsViewModel;
_statisticsViewModel.FinishedGatheringStatisticsForAllFiles += FinishedGatheringStatistics;
if (_statisticsViewModel.IsDataUpToDate)
{
// It either finished before we could hook the event, or we hit the race condition.
FinishedGatheringStatistics(_statisticsViewModel, null);
}
}

private void FinishedGatheringStatistics(object sender, EventArgs e)
{
_statisticsViewModel.FinishedGatheringStatisticsForAllFiles -= FinishedGatheringStatistics;
// Check for race condition (see above).
if (_progressStats != null)
return;

_progressStats = new ProgressStats(_statisticsViewModel);
}
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

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

The new analytics tracking functionality (TrackStatistics, ReportProgressIfAny, and ProgressStats class) lacks test coverage. Since the repository has comprehensive test coverage for both Project and StatisticsViewModel classes, similar test coverage should be added for these new analytics-related methods to verify correct tracking behavior and edge cases.

Copilot uses AI. Check for mistakes.
Comment on lines +970 to +974
// Check for race condition (see above).
if (_progressStats != null)
return;

_progressStats = new ProgressStats(_statisticsViewModel);
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

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

Potential race condition: _progressStats is accessed from multiple contexts (FinishedGatheringStatistics callback, ReportProgressIfAny, and Dispose) without synchronization. While the null check at line 971 helps, a more robust approach would be to use locking or Interlocked operations to ensure thread-safe access to this field, especially since the statistics gatherer runs on a background thread.

Suggested change
// Check for race condition (see above).
if (_progressStats != null)
return;
_progressStats = new ProgressStats(_statisticsViewModel);
// Use atomic initialization to avoid race conditions when multiple threads
// access _progressStats concurrently.
var newProgressStats = new ProgressStats(_statisticsViewModel);
if (Interlocked.CompareExchange(ref _progressStats, newProgressStats, null) != null)
{
// Another thread has already initialized _progressStats; discard this instance.
// If ProgressStats implements IDisposable, it should be disposed here.
}

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 20 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • src/SayMore/UI/SplashScreenForm.Designer.cs: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +953 to +965
public void TrackStatistics(StatisticsViewModel statisticsViewModel)
{
if (_statisticsViewModel != null)
_statisticsViewModel.FinishedGatheringStatisticsForAllFiles -= FinishedGatheringStatistics;

_statisticsViewModel = statisticsViewModel;
_statisticsViewModel.FinishedGatheringStatisticsForAllFiles += FinishedGatheringStatistics;
if (_statisticsViewModel.IsDataUpToDate)
{
// It either finished before we could hook the event, or we hit the race condition.
FinishedGatheringStatistics(_statisticsViewModel, null);
}
}
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

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

The new TrackStatistics method and analytics tracking logic lack test coverage. Consider adding tests to verify: 1) TrackStatistics is called when StatisticsViewModel is created, 2) ReportProgressIfAny correctly tracks deltas, 3) Analytics.Track is called with expected properties.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We don't generally test Analytics code. Given the asyncronous nature of the statistics collection, it's probably not worth the trouble to introduce potentially flaky tests.

Copy link
Collaborator Author

@tombogle tombogle left a comment

Choose a reason for hiding this comment

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

@tombogle made 3 comments and resolved 1 discussion.
Reviewable status: all files reviewed, 3 unresolved discussions (waiting on @andrew-polk).


src/SayMore/Model/Project.cs line 680 at r2 (raw file):

Previously, andrew-polk wrote…

SetAdditionalMetsData

typo
SetAdditionalMetaData

It really is METS. It's an acronym for Metadata Encoding and Transmission Standard (https://www.loc.gov/standards/mets/)

Comment on lines +953 to +965
public void TrackStatistics(StatisticsViewModel statisticsViewModel)
{
if (_statisticsViewModel != null)
_statisticsViewModel.FinishedGatheringStatisticsForAllFiles -= FinishedGatheringStatistics;

_statisticsViewModel = statisticsViewModel;
_statisticsViewModel.FinishedGatheringStatisticsForAllFiles += FinishedGatheringStatistics;
if (_statisticsViewModel.IsDataUpToDate)
{
// It either finished before we could hook the event, or we hit the race condition.
FinishedGatheringStatistics(_statisticsViewModel, null);
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We don't generally test Analytics code. Given the asyncronous nature of the statistics collection, it's probably not worth the trouble to introduce potentially flaky tests.

Copy link
Contributor

@andrew-polk andrew-polk left a comment

Choose a reason for hiding this comment

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

@andrew-polk resolved 1 discussion and dismissed @copilot[bot] from a discussion.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @tombogle).

Copy link

Copilot AI commented Jan 13, 2026

@andrew-polk I've opened a new pull request, #261, to work on those changes. Once the pull request is ready, I'll request review from you.

@andrew-polk
Copy link
Contributor

Sigh. I don't know why copilot did that. Closing it.

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