mbdavid / LiteDB

LiteDB - A .NET NoSQL Document Store in a single data file

Home Page:http://www.litedb.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Use EnterTransaction() before EnterLock(name) exceptions with v5.0.19

zorgoz opened this issue · comments

I am using LiteDb as a singleton without any explicit transactions. It is merely a cache for me, not much actual concurrency is there. All tasks use their respective collections, with no concurrency at all on the collection level.
I am getting such an exception:

LiteDB.LiteException: Use EnterTransaction() before EnterLock(name)
at LiteDB.Engine.EngineState.Validate()

Then all consequent calls fail with the same or with:

Object name: 'System.Threading.ReaderWriterLockSlim'.
at System.Threading.ReaderWriterLockSlim.TryEnterReadLockCore(TimeoutTracker timeout)
at System.Threading.ReaderWriterLockSlim.TryEnterReadLock(TimeSpan timeout)
at LiteDB.Engine.LockService.EnterTransaction()

Switching from 5.0.19 back to 5.0.17 instantly solved the issue.

I also use a singleton instance and consume it in a transient service that gets invoked by a scheduler, very simple code I've used in other projects for years and seemingly at random the same issue popped up. I'll try letting my service run with an older version now like you suggested and see if it goes away, thank you!

Hm, odd, after the downgrade and letting it run for an hour I now consistently run into a different error with v5.0.17:

[15:45:05 ERR] Unhandled exception in processing job
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Threading.ReaderWriterLockSlim'.
   at System.Threading.ReaderWriterLockSlim.TryEnterReadLockCore(TimeoutTracker timeout)
   at System.Threading.ReaderWriterLockSlim.TryEnterReadLock(TimeSpan timeout)
   at LiteDB.Engine.LockService.EnterTransaction()
   at LiteDB.Engine.TransactionMonitor.GetTransaction(Boolean create, Boolean queryOnly, Boolean& isNew)
   at LiteDB.Engine.LiteEngine.Query(String collection, Query query)
   at LiteDB.LiteQueryable`1.ToDocuments()+MoveNext()
   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found)
   at Service.Commands.SearchResultCommandHandler.Handle(SearchResultCommand request, CancellationToken cancellationToken)

Faulty code:

internal class SearchResultCommandHandler : IRequestHandler<SearchResultCommand>
{
    private readonly LiteDatabase _db;
    private readonly ILogger<SearchResultCommandHandler> _logger;
    private readonly IMediator _mediator;

    public SearchResultCommandHandler(ILogger<SearchResultCommandHandler> logger, IMediator mediator, LiteDatabase db)
    {
        _logger = logger;
        _mediator = mediator;
        _db = db;
    }

    public Task Handle(SearchResultCommand request, CancellationToken cancellationToken)
    {
        try
        {
            ILiteCollection<StateEntity>? collection = _db.GetCollection<StateEntity>("Searches");

            StateEntity entity = collection.FindOne(entry => entry.SearchTerm == request.SearchTerm) ??
                                 new StateEntity { SearchTerm = request.SearchTerm };
			...
		}
	}
}

I don't really see any API misuse here 🤔

I an confirm this same

the following code worked many months perfect on version 5.0.17, but after upgrade to 5.0.19 it started to fail.

public List<Order> LoadOrdersByStatus(OrderStatus status)
{
	var col = Db.GetCollection<Order>();
	col.EnsureIndex(x => x.OrderStatusId);
	var statusId = (int)status;
	return col.Find(r => r.OrderStatusId == statusId).ToList();
}

LiteDB.LiteException: Use EnterTransaction() before EnterLock(name)
at LiteDB.Engine.LiteEngine.AutoTransaction[T](Func2 fn) at LiteDB.Engine.LiteEngine.EnsureIndex(String collection, String name, BsonExpression expression, Boolean unique) at LiteDB.LiteCollection1.EnsureIndex(String name, BsonExpression expression, Boolean unique)
at Salamander.Data.Logics.OrderStorage.LoadOrdersByStatus(OrderStatus status)
at Salamander.Data.Logics.OrderStorage.LoadUserCartOrder(Nullable1 userId) at Salamander.Data.Logics.OrderStorage.<>c__DisplayClass13_0.<GetUserCartOrderId>b__0(ICacheEntry entry) at Microsoft.Extensions.Caching.Memory.CacheExtensions.GetOrCreate[TItem](IMemoryCache cache, Object key, Func2 factory)
at Salamander.WebHost.Pages.Shared.Pages_Shared__LayoutHeaderPartial.ExecuteAsync()
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, Boolean invokeViewStarts)
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
at Microsoft.AspNetCore.Mvc.TagHelpers.PartialTagHelper.RenderPartialViewAsync(TextWriter writer, Object model, IView view)
at Microsoft.AspNetCore.Mvc.TagHelpers.PartialTagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)
at Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.g__Awaited|0_0(Task task, TagHelperExecutionContext executionContext, Int32 i, Int32 count)
at Salamander.WebHost.Pages.Shared.Pages_Shared__Layout.b__58_2()
at Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.SetOutputContentAsync()
at Salamander.WebHost.Pages.Shared.Pages_Shared__Layout.ExecuteAsync()
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, Boolean invokeViewStarts)
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderLayoutAsync(ViewContext context, ViewBufferTextWriter bodyWriter)
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable1 statusCode) at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable1 statusCode)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.ResponseCompression.ResponseCompressionMiddleware.InvokeCore(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.HandleException(HttpContext context, ExceptionDispatchInfo edi)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

Thanks folks, I was starting to think I was imagining things, something sure broke over the past 2 releases 😅

I have the same error, but the location of the error is slightly different.
Occurs in 5.0.19, does not occur in 5.0,16.

DB Update Error : LiteDB.LiteException: Use EnterTransaction() before EnterLock(name)
   at LiteDB.Engine.LockService.EnterLock(String collectionName)
   at LiteDB.Engine.Snapshot..ctor(LockMode mode, String collectionName, HeaderPage header, UInt32 transactionID, TransactionPages transPages, LockService locker, WalIndexService walIndex, DiskReader reader, DiskService disk, Boolean addIfNotExists)
   at LiteDB.Engine.TransactionService.CreateSnapshot(LockMode mode, String collection, Boolean addIfNotExists)
   at LiteDB.Engine.LiteEngine.<>c__DisplayClass27_0.<Update>b__0(TransactionService transaction)
   at LiteDB.Engine.LiteEngine.AutoTransaction[T](Func`2 fn)
   at LiteDB.LiteCollection`1.Update(T entity)

Could this be recognized and triaged as a bug please, or some explanation provided what we might do wrong otherwise? Cheers.

I can confirm this behavior, rolled back to 5.0.17
Also using without any transactions.

I can confirm this behavior too(, rolled back to 5.0.17

Thank you for reporting this issue.

This issue has been resolved in the latest version of LiteDB.
Please update to the latest version of LiteDB to resolve this issue.
If the issue persists, please let us know.

This issue has been resolved in the latest version of LiteDB.

Thank you! Could you provide a commit or PR with the cause/fix or briefly explain what the issues was? Thx!

This issue has been resolved in the latest version of LiteDB.

Thank you! Could you provide a commit or PR with the cause/fix or briefly explain what the issues was? Thx!
@nefarius
#2488