❔ ✅ How to implement pool tracking in concurrent list ?
I am trying to add tracking to my logging service. (Web API project)
Once track count is matched, I disbound the ConcurrentBag and send list to logger service.
I need review in this approach where I don't want to lose log data since this method is called in every request.
32 Replies
Your goal is to batch requests to send to Kafka? And of course don't lose or duplicate any data
Yes correct, I am more confused about tracking and pooling
A potential issue I can forsee is if two requests come in, they both start a new task to take items out of the DataList. Still that will result in multiple batches, not necessarely in duplicate or missing data
TryTake gurantees the no duplicate ?
I would guess the TryTake is atomic
The docs don't say much, so let's peek into the source code!
https://source.dot.net/#System.Collections.Concurrent/System/Collections/Concurrent/ConcurrentBag.cs,ac8fb3381a7110eb
okay never mind 😅
It works with CurrentThread which I guess euqals to using lock so, I believe its thread safe and no duplicates
I'm pretty sure it's safe 👍
I am still open for review if anything I misuse here
What's the reason you're starting a new task? If the
SendToKafkaApi
fails, will you catch or retry it?
and I think the recommended way to start tasks like this is by Task.Run(async () =>
There was CPU bound operation inside SendToKafkaApi and simply not awaiting it didn't solve the issue
and it affected response time
CPU bound work like you can think it behave Thrad.Sleep in some point
its solved anyways but still
I think I would store a reference to the created task, and don't start a new one until the existing one completes
Because now if 100 requests would come in before the first one starts TryTake'ing, there will be 100 tasks
and TrackCount keeps increaseing while other Task is Trying to Take, thats another issue
What is the purpose of the Try-Catch? It will not catch any exceptions that happen inside the Task
correct, its not needed
TrackCount doesn't update as far as I can see.
Even if there is 5 items in the Bag and TrackCount is 50, the 45 extra iterations are harmless and won't do anything
I'm not sure how I would approach this. I would probably use Rx and create a
Subject<T>
which this middleware will push items into. Then using the Rx batching things, I'd create batches and send those batches somewherewhat do you mean by Rx ?
The NuGet package Reactive Extensions
https://github.com/dotnet/reactive
GitHub
GitHub - dotnet/reactive: The Reactive Extensions for .NET
The Reactive Extensions for .NET. Contribute to dotnet/reactive development by creating an account on GitHub.
the concepts are documented in https://reactivex.io/
and there are implementations for many languages
you can have subjects which stream data and you can subscribe to them to receive data
more modern than
event
in C#aka observer pattern as they mentioned
this is a kind of basic example, but you can set up subscribes for a subject, and they will each get their callback executed when data is added to the subject
or you can do
there is a lot of helper methods
this one would buffer every 5 emails so we send batch emails, but you can also set a time limit
Woah this one is really interesting https://gist.github.com/omnibs/6b2cbdba2685693448ee6779736a00c2!
We need to run load test and some extra controls after adding packages to core operations. I will try to solve this with simple approach or use existing observer impalmentation in existing codebase
Discuss with your team when you want to add packages like this. It can save you a lot of time and do work for you, but it also takes time to learn :)
yep 😄
for your example, I'd look into what happens if SendToKafkaApi fails (e.g. throws an error)
Do you want to retry the call or put it back into the Bag?
no SendToKafkaApi handles exceptions within, either log on file or retry
@cuddlevde1 how does it look like ? Simpler
1. Making a lot of tasks adds a lot of resources compared to saving a list of items & starting one task to send all items.
2. Inbetween
_tasks.ToList()
and _tasks.Clear()
, a new items can be put in the Bag, which is then deleted
I would stick to having a list of items and sending a batch once in a whileyeah makes sense, not simpler 🙂
I end up using this block
Hmm did you trigger this @Atakan / Cracker or did something else close it?
I did, force of habit. Removing idle tasks 😄
no problem!
Looks like nothing has happened here. I will mark this as stale and this post will be archived until there is new activity.