Skip to content

Session cleanup never deletes anything: NullReferenceException in the tenant filter on every run #1405

Closed
fullstackhero/docs
#256

Description

@marcelo-maciel

Problem

SessionCleanupHostedService (Identity) is supposed to delete, once an hour, every UserSession that expired more than 30 days ago. In practice it never deletes anything. On a running API (Production config, PostgreSQL) every hourly run logs Error during session cleanup with:

System.NullReferenceException: Object reference not set to an instance of an object.
   at lambda_method2944(Closure, QueryContext)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteDeleteAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at FSH.Modules.Identity.Services.SessionCleanupHostedService.CleanupExpiredSessionsAsync(CancellationToken cancellationToken)
   at FSH.Modules.Identity.Services.SessionCleanupHostedService.ExecuteAsync(CancellationToken stoppingToken) in SessionCleanupHostedService.cs:line 40

The service creates a plain DI scope and runs db.UserSessions.Where(s => s.ExpiresAt < cutoff).ExecuteDeleteAsync(). A hosted service has no HTTP request, so Finbuckle never resolves a tenant. UserSession is not an IGlobalEntity, so the default-on tenant isolation in IdentityDbContext puts a tenant query filter on it, and that filter dereferences the (null) current tenant when EF evaluates the query parameters. The loop catches the exception, logs it and tries again an hour later, so the failure is silent apart from the log line, and the UserSessions table grows without bound in every tenant.

Reproduction

  1. Run the API against PostgreSQL with at least one tenant that has a session whose ExpiresAt is more than 30 days in the past.
  2. Wait for the hourly cleanup tick (or invoke SessionCleanupHostedService.CleanupExpiredSessionsAsync directly).
  3. The log shows Error during session cleanup with the NullReferenceException above, and the expired row is still in identity."UserSessions".

Expected

Each run deletes, in every tenant (including tenants with their own connection string), the sessions that expired more than 30 days ago, and keeps sessions that are still valid or expired within the retention window. A failure in one tenant should be logged with that tenant's id without stopping the cleanup of the others.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions