Project Reactor Schedulers elastic using old threadlocal value - spring-webflux

I am using spring webflux to call one service from another via Schedulers.elastic()
Mono<Integer> anaNotificationCountObservable = wrapWithRetryForFlux(wrapWithTimeoutForFlux(
notificationServiceMediatorFlux.getANANotificationCountForUser(userId).subscribeOn(reactor.core.scheduler.Schedulers.elastic())
)).onErrorReturn(0);
In main thread i am setting one InhertitableThreadLocal variable and in the child thread I am trying to access it and it is working fine.
This is my class for storing threadlocal
#Component
public class RequestCorrelation {
public static final String CORRELATION_ID = "correlation-id";
private InheritableThreadLocal<String> id = new InheritableThreadLocal<>();
public String getId() {
return id.get();
}
public void setId(final String correlationId) {
id.set(correlationId);
}
public void removeCorrelationId() {
id.remove();
}
}
Now the issue is first time its working fine meaning the value i am setting in threadlocal is passed to other services.
But second time also, it is using old id(generated in last request).
I tried using Schedulers.newSingle() instead of elastic(), then its working fine.
So think since elastic() is re-using threads, thats why it is not able to clear / or it is re-using.
How should i resolve issue.
I am setting thread local in my filter and clearing the same in myfiler
requestCorrelation.setId(UUID.randomUUID().toString());
chain.doFilter(req,res)
requestCorrelation.removeCorrelationId();

You should never tie resources or information to a particular thread when leveraging a reactor pipeline. Reactor is itself scheduling agnostic; developers using your library can choose to schedule work on another scheduler - if you decide to force a scheduling model you might lose performance benefits.
Instead you can store data inside the reactor context. This is a map-like structure that’s tied to the subscriber and independent of the scheduling arrangement.
This is how projects like spring security and micrometer store information that usually belongs in a threadlocal.

Related

How do you perform completely asynchrouns operations in ASP NET Core

Hello i am trying to do a trail log for some of my API endpoints.These logs are generated when the endpoint is called.I would like the writing of the logs to be done in an asynchrouns manner (as lightweight as possible) as to not affect the performance of my usual logic.
I was thinking to have a component that is injectable and can be called anywhere in my endpoints when a log is produced.The problem is that i seem to not find a suitable async solution:
Important service that needs not be obstructed by delays
public interface IImportantInterface
{
Task DoSomethingUndistrubedAsync(string value);
}
**Wrapper around Redis pub-sub**
public interface IIOService{
Task PublishAsync( object obj);
}
Controller
public class Controller
{
private IImportantInterface importantService;
private Publisher publisher;
[HttpPost]
public async Task SomeEndpointAsync(){
this.publisher.Publish([some_log]);
await this.importantService.DoSomethingUndisturbedAsync([something]);
}
public Controller(IImportantInterface importantService)
{
this.importantService=importantService;
}
}
Now comes the real problem.How do i make the smallest footprint for my Publisher.I came up with 3 scenarios but two of them are unfeasible due to going out of scope:
Attempt 1
Transient Service with Task scoped to method:
public class Publisher{
private IIOService writeService{get;set;}
public async Task PublishAsync(object obj){
Task t1=Task.Run(async()=>await writeService.PublishAsync(obj)); //t1 might not finished when method exits
}
}
Task t1 might not finish by the time the method ends.
Attempt 2
Task embedded in Transient Service
public class Publisher{ //publisher might get discarded when calling controller gets out of scope
private Task t1;
private IIOService writeService{get;set;}
public async Task PublishAsync(object obj){
t1=Task.Run(async ()=> this.IIOService.writeService(obj));
}
}
Now task will not get collected after method scope , but it might not finish by the time the calling Controller method class gets out of scope
Attempt 3
Singleton object with a ConcurrentQueue of Tasks that get enqueued.
This would not get out of scope but when would i clear the items?
public class Publisher{
private ConcurrentQueue<Task> Queue;
public async Task PublishAsync(object obj){
this.Queue.Enqueue();
}
}
P.S I want to publish these logs in a common place.From that place the target is to get published to a Redis database using the pub-sub functionality.
Should i just write to Redis ?
Hello i am trying to do a trail log for some of my API endpoints.These logs are generated when the endpoint is called.I would like the writing of the logs to be done in an asynchrouns manner (as lightweight as possible) as to not affect the performance of my usual logic.
I strongly recommend that you use an existing and exhaustively-tested logging library, of which there are many with modern capabilities such as semantic logging and async-compatible implicit state.
Modern logging libraries generally have a singleton kind of design, where logs are kept in-memory (and logging methods are synchronous). Then there is a separate "processor" which publishes these messages to a collector. If you insist on writing your own logging framework (why?), I would recommend you take the same approach as all the other highly successful logging frameworks.

WebApplicationFactory and TestServer in integration tests for ASP.NET Core

I have two integ test classes defined as below. When I run tests in ApiControllerIT, all runs successfully. The same for FoundationControllerIT. However, when I run both together (by running the enclosing folder), tests fail.
The error message is:
Scheduler with name 'DefaultQuartzScheduler' already exists.
I have this definition in my Startup.cs file:
services.AddSingleton (IHostedService, QuartzHostedService);
So obviously this line causes the issue (if I remove this line, all testing together runs OK). So my question is - I'm a newbie from Java.. so I don't have a very good insight into .NET Core Integ test framework, but my understanding is - TestServer is created for each of test classes, e.g. One TestServer for ApiControllerIT, and the other for FoundationControllerIT. Is this incorrect? I'm just frustrated how come I'm getting a message:
Scheduler with name 'DefaultQuartzScheduler' already exists.
when I run two separate test classes?? How come the TestServers interfere each other?
public class ApiControllerIT : IClassFixture<WebApplicationFactory<Startup>>
{
private readonly WebApplicationFactory<Startup> _factory;
public ApiControllerIT(WebApplicationFactory<Startup> factory)
{
_factory = factory;
}
// tests ...
}
public class FoundationControllerIT : IClassFixture<WebApplicationFactory<Startup>>
{
private readonly WebApplicationFactory<Startup> _factory;
public FoundationControllerIT(WebApplicationFactory<Startup> factory)
{
_factory = factory;
}
// tests ...
}
I might a bit late on this but I also had this problem and it might still be useful for others in the future.
The problem comes because the WebApplicationFactory will create two instances of your Startup class. This is drastically different from your normal service start, where you only have one instance of Startup.
(It might be a bit different in your case, but I am using a Singleton instance to create and manage my Schedulers throughout my application.)
The WebApplicationFactory also calls ConfigureServices and Configure on both of them. So even your singletons will be there twice, one for each Startup instance. This is not a problem because the Startup instances will have their own ServiceProvider. It only comes to problems if (multiple) singleton instances access the same static properties of something. In our case, this is the SchedulerBuilder using SchedulerFactory using SchedulerRepository within Quartz, which is a >real< singleton and uses this code:
/// <summary>
/// Gets the singleton instance.
/// </summary>
/// <value>The instance.</value>
public static SchedulerRepository Instance { get; } = new SchedulerRepository();
This means that your independent Singleton classes still use the same SchedulerRepository within Quartz, which explains why you get the exception.
Depending on what you are testing within your tests you have some options to tackle this issue.
The SchedulerRepository has a lookup method, which you could use to check if the Scheduler was already created by another instance: public virtual Task<IScheduler?> Lookup(string schedName, CancellationToken cancellationToken = default) - So you either just take the existing Scheduler or you generate another one with a different name
Catch the exception and do nothing. (this only really makes sense if your tests do not need Quartz, which is probably unlikely but I still wanted to list this option)
I cannot tell you what makes most sense in your case as this is completely dependent on what your application does and what you want to test, but I will probably stick with one variant of option 1.

How to keep vaadin application instances from interfering with eachother?

I've got a Vaadin application and I'm getting some strange behaviour when running two instances of the application at the same time (one in FF, another in IE). I've already removed most static objects (these caused the application to completely reload when used parallel to another open application) and now I can interact normally with the UI without the complete reset. However, I'm now noticing that I'm getting only one user's data in both interfaces. I assume this is caused by singleton objects I'm using to manage some data caching and a SOAP connection. I'd like to know if it's the singleton pattern itself that's causing the strange output or is it just the static instance object I'm keeping?
I've tried using ThreadLocal with my singleton, but all my variables are always null when I try to use them in my singleton's functions. Currently my singleton contains this, which is probably terribly, terribly wrong since it doesn't work.
private static ThreadLocal<SoapClient> instance = new ThreadLocal<SoapClient>();
public static synchronized SoapClient getInstance(){
if (instance.get() == null) {
instance.set(new SoapClient());
}
return instance.get();
}
I chose a singleton object so I'd always have access to the cached data and my user's soap connection everywhere in my application instance, and the only other way I can think of for doing that is to have a static object somewhere, but the static keyword seems to be the cause of all my problems in the first place. Is there any way around this or is there something else causing it?
A better way to instantiate your thread local would be this
ThreadLocal<SoapClient> instance = new ThreadLocal<String>() {
#Override
protected String initialValue() {
return new SoapClient();
}
}
However, your problem here is web app servers "pool" and re-use threads. In Vaadin terms,not every request for an application is processed same thread - i.e. Thread1 could process requests for both App instance 1 and App Instance 2. If your SoapClient caches information appropriate to App instance 1, the UI for App 2 could end up using the SoapClient for App 1.
Assuming (from your description) that "app specific" information is cached in the SoapClient, I would suggest that you
Create and store the SoapClient on your Application object as a normal field (not static, not threadlocal)
If you need to access the application (in order to get the SoapClient), and it's tricky from where you are, use the ThreadLocal access pattern. See the second example on the link. Note that the ThreadLocal is set at the beginning of the HttpRequest, and "unset" at the end, ensuring that any subsequent requests on the same thread do NOT get the same application instance.

IQueryable Repository with StructureMap (IoC) - How do i Implement IDisposable?

If i have the following Repository:
public IQueryable<User> Users()
{
var db = new SqlDataContext();
return db.Users;
}
I understand that the connection is opened only when the query is fired:
public class ServiceLayer
{
public IRepository repo;
public ServiceLayer(IRepository injectedRepo)
{
this.repo = injectedRepo;
}
public List<User> GetUsers()
{
return repo.Users().ToList(); // connection opened, query fired, connection closed. (or is it??)
}
}
If this is the case, do i still need to make my Repository implement IDisposable?
The Visual Studio Code Metrics certainly think i should.
I'm using IQueryable because i give control of the queries to my service layer (filters, paging, etc), so please no architectural discussions over the fact that im using it.
BTW - SqlDataContext is my custom class which extends Entity Framework's ObjectContext class (so i can have POCO parties).
So the question - do i really HAVE to implement IDisposable?
If so, i have no idea how this is possible, as each method shares the same repository instance.
EDIT
I'm using Depedency Injection (StructureMap) to inject the concrete repository into the service layer. This pattern is followed down the app stack - i'm using ASP.NET MVC and the concrete service is injected into the Controllers.
In other words:
User requests URL
Controller instance is created, which receives a new ServiceLayer instance, which is created with a new Repository instance.
Controller calls methods on service (all calls use same Repository instance)
Once request is served, controller is gone.
I am using Hybrid mode to inject dependencies into my controllers, which according to the StructureMap documentation cause the instances to be stored in the HttpContext.Current.Items.
So, i can't do this:
using (var repo = new Repository())
{
return repo.Users().ToList();
}
As this defeats the whole point of DI.
A common approach used with nhibernate is to create your session (ObjectContext) in begin_request (or some other similar lifecycle event) and then dispose it in end_request. You can put that code in an HttpModule.
You would need to change your Repository so that it has the ObjectContext injected. Your Repository should get out of the business of managing the ObjectContext lifecycle.
I would say you definitely should. Unless Entity Framework handles connections very differently than LinqToSql (which is what I've been using), you should implement IDisposable whenever you are working with connections. It might be true that the connection automatically closes after your transaction successfully completes. But what happens if it doesn't complete successfully? Implementing IDisposable is a good safeguard for making sure you don't have any connections left open after your done with them. A simpler reason is that it's a best practice to implement IDisposable.
Implementation could be as simple as putting this in your repository class:
public void Dispose()
{
SqlDataContext.Dispose();
}
Then, whenever you do anything with your repository (e.g., with your service layer), you just need to wrap everything in a using clause. You could do several "CRUD" operations within a single using clause, too, so you only dispose when you're all done.
Update
In my service layer (which I designed to work with LinqToSql, but hopefully this would apply to your situation), I do new up a new repository each time. To allow for testability, I have the dependency injector pass in a repository provider (instead of a repository instance). Each time I need a new repository, I wrap the call in a using statement, like this.
using (var repository = GetNewRepository())
{
...
}
public Repository<TDataContext, TEntity> GetNewRepository()
{
return _repositoryProvider.GetNew<TDataContext, TEntity>();
}
If you do it this way, you can mock everything (so you can test your service layer in isolation), yet still make sure you are disposing of your connections properly.
If you really need to do multiple operations with a single repository, you can put something like this in your base service class:
public void ExecuteAndSave(Action<Repository<TDataContext, TEntity>> action)
{
using (var repository = GetNewRepository())
{
action(repository);
repository.Save();
}
}
action can be a series of CRUD actions or a complex query, but you know if you call ExecuteAndSave(), when it's all done, you're repository will be disposed properly.
EDIT - Advice Received From Ayende Rahien
Got an email reply from Ayende Rahien (of Rhino Mocks, Raven, Hibernating Rhinos fame).
This is what he said:
You problem is that you initialize
your context like this:
_genericSqlServerContext = new GenericSqlServerContext(new
EntityConnection("name=EFProfDemoEntities"));
That means that the context doesn't
own the entity connection, which means
that it doesn't dispose it. In
general, it is vastly preferable to
have the context create the
connection. You can do that by using:
_genericSqlServerContext = new GenericSqlServerContext("name=EFProfDemoEntities");
Which definetely makes sense - however i would have thought that Disposing of a SqlServerContext would also dispose of the underlying connection, guess i was wrong.
Anyway, that is the solution - now everything is getting disposed of properly.
So i no longer need to do using on the repository:
public ICollection<T> FindAll<T>(Expression<Func<T, bool>> predicate, int maxRows) where T : Foo
{
// dont need this anymore
//using (var cr = ObjectFactory.GetInstance<IContentRepository>())
return _fooRepository.Find().OfType<T>().Where(predicate).Take(maxRows).ToList();
And in my base repository, i implement IDisposable and simply do this:
Context.Dispose(); // Context is an instance of my custom sql context.
Hope that helps others out.

WCF data persistence between sessions

We are developing a WCF based system. In the process we are trying to lock some data from being modified by more than one users. So we decided to have a data structure that will contain the necessary information for the locking logic to execute (by for example storing the ID of the locked objects)
The problem we are having is persisting that data between sessions. Is there anyway we can avoid executing expensive database calls?
I am not sure how can we do that in WCF since it can only persist data (in memory) during an open session.
Static members of the service implementing class are shared between sessions & calls.
One option would be to use static members as Jimmy McNulty said. I have a WCF service that opens network connections based on a user-specified IP address. My service is configured for PerCall service instance mode. In each session, I check a static data structure to see if a network connection is already opened for the specified IP address. Here's an example.
[ServiceContract]
public interface IMyService
{
[OperationContract]
void Start(IPAddress address);
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class MyService : IMyService
{
private static readonly List<IPAddress> _addresses = new List<IPAddress>();
public void Start(IPAddress address)
{
lock(((ICollection)_addresses).SyncRoot)
{
if (!_addresses.Contains(address)
{
// Open the connection here and then store the address.
_addresses.Add(address);
}
}
}
}
As configured, each call to Start() happens within its own service instance, and each instance has access to the static collection. Since each service instance operates within a separate thread, access to the collection must be synchonized.
As with all synchronization done in multithreaded programming, be sure to minimize the amount of time spent in the lock. In the example shown, once the first caller grabs the lock, all other callers must wait until the lock is released. This works in my situation, but may not work in yours.
Another option would be to use the Single service instance mode as opposed to the PerCall service instance mode.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class MyService : IMyService
{ ... }
From everything I've read, though, the PerCall seems more flexible.
You can follow this link for differences between the two.
And don't forget that the class that implements your service is just that - a class. It works like all C# classes do. You can add a static constructor, properties, event handlers, implement additional interfaces, etc.
Perhaps a caching framework like velocity help you out.
Create a second class and set its InstanceContextMode to single and move all the expensive methods there, then in your original class use that methods.