Skip to content
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

Sessions Storage for CookieStickySessions #1405

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from

Conversation

EliSyrota
Copy link

@EliSyrota EliSyrota commented Dec 29, 2020

Problem to solve

The current implementation of CookieStickySessions contains ConcurrentDictionary<string, StickySession> _stored where all the sessions are stored.
We faced a situation when we need to have a few Ocelot instances on-premise of the customer
and we have some services that enforces us to use CookieStickySessions for our Load Balancer (https://ocelot.readthedocs.io/en/latest/features/loadbalancer.html#cookiestickysessions).
Having several instances of Ocelot push us to add the ability to use CookieStickySessions for LoadBalancing across these several Ocelot instances.
To do so we need to have an ability to inject our own session storage implementation for CookieStickySessions

New Feature

  • Sessions storage implementations for CookieStickySessions
  • Add the ability to use CookieStickySessions for LoadBalancing across these several ocelot instances

Proposed Changes

To do so, we need to:

  • extract sessions collection from CookieStickySessions
  • make a public interface for session storage so users can implement their own mechanism of storing user sessions such as distributed sessions storage etc.
  • substitute CookieStickySessionsCreator to inject into CookieStickySessions own storage mechanism

@EliSyrota EliSyrota changed the title InMemoryStickySessionStorage for CookieStickySessions Sessions Storage for CookieStickySessions Dec 29, 2020
@raman-m raman-m added feature A new feature proposal Proposal for a new functionality in Ocelot needs feedback Issue is waiting on feedback before acceptance labels Jul 11, 2023
@raman-m raman-m self-requested a review July 11, 2023 17:36
@raman-m
Copy link
Member

raman-m commented Aug 22, 2023

Hi @EliSyrota !
Thanks for the great PR and your interest in Ocelot!
I know you're requesting a new feature, but could this PR be related to an issue in the backlog?


The feature branch (develop) has been rebased onto ThreeMammals:develop!
Welcome to code review!
Good luck!

Copy link
Member

@raman-m raman-m left a comment

Choose a reason for hiding this comment

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

Major issues are

  • No unit tests for newly added InMemoryStickySessionStorage class
  • No new unit tests in CookieStickySessionsTests, but behavior of CookieStickySessions class has changed. New parameter for the constructor should be tested.
  • No tests for CookieStickySessionsCreator

I believe, current design can be enhanced a bit, to allow to developer not implementing ILoadBalancerCreator interface, but simply replace InMemoryStickySessionStorage class by custom one in DI-container for IStickySessionStorage interface.

Copy link
Member

Choose a reason for hiding this comment

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

This new class should be covered by unit tests!

@@ -41,7 +41,8 @@ public CookieStickySessionsTests()
_bus = new FakeBus<StickySession>();
_loadBalancer = new Mock<ILoadBalancer>();
_defaultExpiryInMs = 0;
_stickySessions = new CookieStickySessions(_loadBalancer.Object, "sessionid", _defaultExpiryInMs, _bus);
var sessionStorage = new InMemoryStickySessionStorage();
Copy link
Member

Choose a reason for hiding this comment

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

You are in unit tests! You haven't & shouldn't create concrete instance of the class!
You need to create mocked IStickySessionStorage object for the constructor on the next line.

Suggested change
var sessionStorage = new InMemoryStickySessionStorage();
var sessionStorage = new Mock<IStickySessionStorage>();
// setup the mock

@@ -14,8 +15,9 @@ public Response<ILoadBalancer> Create(DownstreamRoute route, IServiceDiscoveryPr
{
var loadBalancer = new RoundRobin(async () => await serviceProvider.Get());
var bus = new InMemoryBus<StickySession>();
var sessionStorage = new InMemoryStickySessionStorage();
Copy link
Member

@raman-m raman-m Aug 22, 2023

Choose a reason for hiding this comment

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

Is it possible to inject this default concrete class from DI-container, and/or via extra argument?
Because this method is responsible for default implementations injection, we need to forward a IStickySessionStorage object to CookieStickySessions constructor.


substitute CookieStickySessionsCreator to inject into CookieStickySessions own storage mechanism

Because this class (creator) is managed by DI-container, we have to add InMemoryStickySessionStorage class to DI-container too, and inject it via constructor. This is the simplest solution!
Finally, developer should not implement new creator inheriting the ILoadBalancerCreator interface.


P.S. See previous line 17. Consider moving of InMemoryBus<StickySession> object to DI-container too while refactoring this class.

@@ -0,0 +1,10 @@
namespace Ocelot.LoadBalancer.LoadBalancers;

public interface IStickySessionStorage
Copy link
Member

@raman-m raman-m Aug 22, 2023

Choose a reason for hiding this comment

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

Well... In PR you said:

  • make a public interface for session storage so users can implement their own mechanism of storing user sessions such as distributed sessions storage etc.

Based on the current code I can say, the interface object is not added to DI-container.

private readonly IBus<StickySession> _bus;
private readonly object _lock = new();

public CookieStickySessions(ILoadBalancer loadBalancer, string key, int keyExpiryInMs, IBus<StickySession> bus)
public CookieStickySessions(ILoadBalancer loadBalancer, string key, int keyExpiryInMs, IBus<StickySession> bus, IStickySessionStorage storage)
Copy link
Member

Choose a reason for hiding this comment

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

substitute CookieStickySessionsCreator to inject into CookieStickySessions own storage mechanism

Because new added interface object can be injected by this creator, we need to explain to developer how to implement custom creator using ILoadBalancerCreator interface.
So, new paragraph in docs is required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature A new feature needs feedback Issue is waiting on feedback before acceptance proposal Proposal for a new functionality in Ocelot
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants