Skip to content

tasklog: introduce *SimpleTask #2756

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

Merged
merged 2 commits into from
Dec 1, 2017
Merged

tasklog: introduce *SimpleTask #2756

merged 2 commits into from
Dec 1, 2017

Conversation

ttaylorr
Copy link
Contributor

This pull request introduces a new Task implementation, *tasklog.SimpleTask, for logging unrelated messages.

This functionality is required in replacing the usage of *progress.Spinner from within the git-lfs-prune(1) command. Instead of building domain-specific Task implementations, this pull request proposes the introduction of a string-based Task implementation that logs (and formats) strings without formatting guidelines.

This allows for quick prototyping of new Logger use-cases without the need to build out domain-specific loggers, and is a good fit for use within the git-lfs-prune(1) command.

/cc @git-lfs/core

@ttaylorr ttaylorr added this to the v2.4.0 milestone Nov 28, 2017
@ttaylorr ttaylorr merged commit 0100df9 into master Dec 1, 2017
@ttaylorr ttaylorr deleted the tasklog-simple-task branch December 1, 2017 17:40
chrisd8088 added a commit to chrisd8088/git-lfs that referenced this pull request May 26, 2023
The SimpleTask structure of the "tasklog" package, which was introduced
in commit 7a760b6 of PR git-lfs#2756, is used
at several points in the implementation of the "git lfs fetch" and
"git lfs prune" commands, and in each case is constructed with a
call to the NewSimpleTask() function, and then passed to a Logger
structure's Enqueue() method.

However, in commit 0cad488 of PR git-lfs#2767,
a Logger.Simple() method was added to both create a new SimpleTask
structure and pass it to a Logger structure's Enqueue() method.  This
Logger.Simple() method was added to be consistent with other existing
similar methods such as Logger.List() and Logger.Percentage().

These other methods are used consistently throughout our code
to create and enqueue tasks, so we now update the locations where
we call NewSimpleTask() to use the Logger.Simple() method instead.

This also provides an opportunity to tidy some of the surrounding
code and whitespace.
chrisd8088 added a commit to chrisd8088/git-lfs that referenced this pull request May 26, 2023
In commit e90d54d of PR git-lfs#2329 the
"git/githistory/log" package was added, including the PercentageTask
structure and associated methods, but unlike the WaitingTask which
was added at the same time, no Complete() method was defined for
the PercentageTask structure.

(Note that the "git/githistory/log" package was later renamed to the
"tasklog" package in commits b9ab79e
and 45c580e of PR git-lfs#2747.)

Other task types such as the ListTask and SimpleTask structures
(introduced in commit 31ffeb9 of
PR git-lfs#2335 and commit 7a760b6 of PR git-lfs#2756,
respectively) provide a Complete() method, and the Meter task type
of the "tq" package, which implemented the Task interface in commit
7c0f9e2 of PR git-lfs#2732, provides an
equivalent Finish() method.  These methods allow the caller to
explicitly close the channel returned by the Updates() method,
on which the anonymous goroutine started by the Logger.consume() method
for the task is waiting, in a "range" loop on the channel in the
Logger.logTask() method.

One key use of the PercentageTask structure is in the methods of
the Rewriter structure from the "git/githistory" package.  It is
initialized with the number of commits to be rewritten during
a "git lfs migrate" command's traversal of a Git repository's history.
As each commit is rewritten, the Count() method is called to
increment the percentage completed value.  When every commit has
been rewritten, the count reaches the expected total, and the
Count() method closes the channel, thus allowing the task receiving
updates to finish and exit its goroutine.

Under exceptional circumstances, though, the Rewrite() method of
the Rewriter structure may never finish iterating through all
the expected commits, and return in error or via a panic call.
When this happens, the goroutine waiting on the PercentageTask's
updates channel can never exit, leading to a hung process which
never fully exits.

In order to allow the Rewriter's Rewrite() method to define a
deferred function which will always be called when it returns,
under any circumstances, we add a Complete() method for the
PercentageTask structure which sets the number of completed elements
to the expected total in an atomic swap, and then closes the
updates channel if the number of completed elements was previously
less than the expected total.

We also add a test to validate this new method's behaviour, and
update the existing TestPercentageTaskCallsDoneWhenComplete()
function to also confirm that calling the new Complete() method
after the number of completed elements has reached the expected
total does not cause a second attempt to close the updates channel.
chrisd8088 added a commit to chrisd8088/git-lfs that referenced this pull request May 26, 2023
In commit e90d54d of PR git-lfs#2329 the
"git/githistory/log" package was added, including the PercentageTask
structure and associated methods, but unlike the WaitingTask which
was added at the same time, no Complete() method was defined for
the PercentageTask structure.

(Note that the "git/githistory/log" package was later renamed to the
"tasklog" package in commits b9ab79e
and 45c580e of PR git-lfs#2747.)

Other task types such as the ListTask and SimpleTask structures
(introduced in commit 31ffeb9 of
PR git-lfs#2335 and commit 7a760b6 of PR git-lfs#2756,
respectively) provide a Complete() method, and the Meter task type
of the "tq" package, which implemented the Task interface in commit
7c0f9e2 of PR git-lfs#2732, provides an
equivalent Finish() method.  These methods allow the caller to
explicitly close the channel returned by the Updates() method,
on which the anonymous goroutine started by the Logger.consume() method
for the task is waiting, in a "range" loop on the channel in the
Logger.logTask() method.

One key use of the PercentageTask structure is in the methods of
the Rewriter structure from the "git/githistory" package.  It is
initialized with the number of commits to be rewritten during
a "git lfs migrate" command's traversal of a Git repository's history.
As each commit is rewritten, the Count() method is called to
increment the percentage completed value.  When every commit has
been rewritten, the count reaches the expected total, and the
Count() method closes the channel, thus allowing the task receiving
updates to finish and exit its goroutine.

Under exceptional circumstances, though, the Rewrite() method of
the Rewriter structure may never finish iterating through all
the expected commits, and return in error or via a panic call.
When this happens, the goroutine waiting on the PercentageTask's
updates channel can never exit, leading to a hung process which
never fully exits.

In order to allow the Rewriter's Rewrite() method to define a
deferred function which will always be called when it returns,
under any circumstances, we add a Complete() method for the
PercentageTask structure which sets the number of completed elements
to the expected total in an atomic swap, and then closes the
updates channel if the number of completed elements was previously
less than the expected total.

We also add a test to validate this new method's behaviour, and
update the existing TestPercentageTaskCallsDoneWhenComplete()
function to also confirm that calling the new Complete() method
after the number of completed elements has reached the expected
total does not cause a second attempt to close the updates channel.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants