-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
WebServiceTarget - FlushAsync - Avoid premature flush #1868
Conversation
…id premature flush
Current coverage is 81% (diff: 92%)@@ master #1868 diff @@
==========================================
Files 276 277 +1
Lines 18634 18748 +114
Methods 2861 2873 +12
Messages 0 0
Branches 2139 2148 +9
==========================================
+ Hits 15138 15260 +122
- Misses 2977 2984 +7
+ Partials 519 504 -15
|
foreach (var key in new List<HttpWebRequest>(_pendingRequests.Keys)) | ||
{ | ||
KeyValuePair<DateTime, AsyncContinuation> flushCallback; | ||
if (_pendingRequests.TryGetValue(key, out flushCallback)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't we need a lock
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FlushAsync is already protected by this.SyncRoot. Same lock-object is used for the other manipulations. But I can add an explicit lock, so it will not confuse.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missed that, thx! No need to add it IMO then
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great that we could close that old issue :)
Some questions, see code notes
catch (NLog.NLogRuntimeException) | ||
{ } | ||
LogManager.Flush(); // Waits for flush (Scheduled on top of the previous flush) | ||
LogManager.Flush(); // Nothing to flush |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should users also do a triple-flush?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No triple flush is only for code-coverage :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds we should have split those tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -180,6 +180,7 @@ public WebServiceTarget(string name) : this() | |||
/// <docgen category='Web Service Options' order='10' /> | |||
public string XmlRootNamespace { get; set; } | |||
|
|||
private readonly Dictionary<HttpWebRequest, KeyValuePair<DateTime,AsyncContinuation>> _pendingRequests = new Dictionary<HttpWebRequest, KeyValuePair<DateTime,AsyncContinuation>>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't HttpWebRequest
an expensive key value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another way would be using a linkedlist and send the info with the AsyncContinuation
(if possible)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't HttpWebRequest an expensive key value?
I was hoping it was acting like a normal class, and just used default class-reference-hashcode.
Another way would be using a linkedlist
Yet another option is just to monitor the last written LogEvent.
And yet yet another option is to have a single counter of outstanding requests, and then keep a queue of flush-callbacks. When a flush is requested one caches the pending request count, and when it reaches zero, then it fires the flush-callback. Then it would only be a list of pending flush-callbacks and a pending-counter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was hoping it was acting like a normal class, and just used default class-reference-hashcode.
yes 're right!
// The default implementation returns the sync block index for this instance.
// Calling it on the same object multiple times will return the same value, so
// it will technically meet the needs of a hash function, but it's less than ideal.
// Objects (& especially value classes) should override this method.
https://referencesource.microsoft.com/#mscorlib/system/object.cs,4de9cf234d0d8b16
Have now also added AutoFlushTargetWrapper into the mix, since #259 also complains that using the AutoFlushTargetWrapper didn't solve their problem. Now I also have the crutch (AutoFlushTargetWrapper) that people can use when having a target without a proper flush-method. Have decided not to keep track of the individual logevents, but just have a pending-counter, and then just keep track of the pending flush-requests instead. |
cb359e9
to
14acb87
Compare
14acb87
to
945a7ca
Compare
437d10d
to
eb51d53
Compare
eb51d53
to
89a8519
Compare
Reviewed 15 of 17 files at r2, 3 of 3 files at r3. tests/NLog.UnitTests/Targets/WebServiceTargetTests.cs, line 626 at r3 (raw file):
nice one :) Comments from Reviewable |
@304NotModified Think I have broken something, as the test-builds are now failing quite frequently, after the merge. Have found the problem. I had broken broken the wait-counter for the two tests. See #1903 |
Keeps track of pendingRequests. Tries to fix #259. Instead of expecting async-target to almost handle it #1853
First idea was to keep track of each individual LogEvent (in a dictionary), but the logic (and the allocations) became a little heavy. Now it just keeps track of a pending request count, so it is not completely correct when races occurs, but I think it is good enough.
This change is