How do I iterate across all sessions in ServiceStack?

橙三吉。 提交于 2020-01-14 04:22:05

问题


Our application has companies and uses in each company. Each company has X number of licenses. We are using a typed session class, and that class contains the id of the company along with other user information. I need to add to our authentication process, a check to see if the current login will exceed a company's licenses. I believe that the way to do this is to get a count of all company Ids across all sessions that match the companyId of the user currently trying to log in, and compare that count to the number of available licenses in our company table. Is this a valid approach? If so, please let me know how to query across all sessions, as I haven't figured it out and I'm still somewhat new to ServiceStack.


回答1:


Using ICacheClientExtended API's

The ICacheClientExtended interface now supports a GetKeysByPattern API that lets you scan for matching keys on Cache Clients that implement the interface. Currently this is implemented by:

  • MemoryCacheClient
  • OrmLiteCacheClient
  • Redis
  • AWS DynamoDbCacheClient

This API now enables the new GetAllKeys() and GetKeysStartingWith() extension methods now available on ICacheClient to scan all cache keys.

var prefix = IdUtils.CreateUrn<IAuthSession>(""); //= urn:iauthsession:
var sessionKeys = Cache.GetKeysStartingWith(sessionPattern).ToList();
var userSessions = Cache.GetValues<AuthUserSession>(sessionKeys);
var existingSessions = userSessions.Values.Where(x => x != null).ToList();

Where existingSessions will contain list of active User Sessions.

Performance will be determined by how many active sessions you have which could be high depending on popularity of your site. Instead of searching all keys you may want to keep a set of session ids per company that you would look through instead by adding them to a collection in a Session or Auth Event.

This new API is available from v4.0.45+ of ServiceStack that's now available on MyGet.

The latest DynamoDbCacheClient is now in the new ServiceStack.Aws NuGet package on MyGet which references the latest v3.* packages from the AWS SDK.


Searching the underlying Caching Provider

Another option is access them directly from your ICacheClient Caching provider if it supports full scans, e.g. if you're using OrmLiteCacheClient to store sessions in an RDBMS you can access all Cache Entries with:

var sessionEntries = Db.Select<CacheEntry>(q => 
    q.Where(x => x.Id.StartsWith("urn:iauthsession:")));
var userSessions = sessionEntries.Map(x => 
    Db.Deserialize<AuthUserSession>(x.Data));

If you're using Redis for Caching you can get it with:

var sessionKeys = Redis.SearchKeys("urn:iauthsession:*");
var sessions = Redis.GetValues<AuthUserSession>(sessionKeys);

Another option would be to maintain a list of all Session Ids for each Company as each user logs in by registering a custom Session or Auth Event which you could maintain in a Redis SET or RDBMS table. In the same registration hook you can verify how many active Sessions they have by using ICacheClient.GetAll API and passing in the session keys for that company, something like:

var sessions = Cache.GetAll<AuthUserSession>(companySessionKeys);
var activeSessions = sessions.Values.Where(x => x != null).ToList();



回答2:


A little speed check:

I am using InMemoryAuthRepository, and if I have 1000 sessions in cache, and I fetch them, it takes 21 ms. The fetching starts at 4 ms (for 1 session) and goes up to 21 ms for a 1000.

sw.Restart();
IDictionary<string, IAuthSession> sessionList = cacheClient?.GetAll<IAuthSession>(cacheClient?.GetAllKeys());
sw.Stop();
totalMs += sw.ElapsedMilliseconds;
counter2speed.Add(counter, totalMs);


来源:https://stackoverflow.com/questions/32459285/how-do-i-iterate-across-all-sessions-in-servicestack

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!