0

So I am writing a server in C#. It has a LiteDB database to store messages in. When I start up the server, I also launch an async task to delete expired messages from the DB (messages that are older than some predefined threshold). Lets call this task the GC (garbage collector).

Every time the server receives a message, it stores the message in the DB, and sends a copy to the proper destination.

Since LiteDB is supposed to be thread-safe, I don't use locks to synchronize reads/writes to the DB. The only synchronization that I do is between the GC and regular read/writes to the DB. For that, I use a reader/writer async lock. I treat the GC as a writer, and all other accesses to the DB are considered readers (since supposedly, LiteDB is thread-safe).

I am wondering if I am correct and this design will work?

I've made a test (on a WPF app) that connects 50 clients, each in a separate task. Each client sends a message to all other clients and expects to receive a message from all other clients. I then make sure that all messages were sent/received as expected. During this test, the GC runs every 3 seconds (every time, keeping the writer lock locked for 1 second, using delay). Each message sent also adds 1-4ms delay.

With 50 clients, the server passes the test fine. However, with 100 clients, I observe some weird behavior that makes me reconsider my design.

Between the first 2-3 times of the writerlock being locked, I see many messages pass properly. However, after these 2-3 times, I suddenly see only one message being sent every second. And the GC stops locking the writerlock. Eventually, after 1 minute of this, I get the following exception:

Exception thrown: 'LiteDB.LiteException' in LiteDB.dll
Database lock timeout when entering in transaction mode after 00:01:00

I assume this means that I have some deadlock somewhere. Perhaps too many messages are waiting to be inserted and hold the reader lock?

Ungoliant
  • 133
  • 2
  • 14
  • How would we know what's wrong about your code without seeing the code? Ideally, post a [mcve]. – Fildor Jul 27 '23 at 15:03
  • I am not asking whether my code is wrong. I am asking generally about my design decisions. Mainly, whether it is indeed a good idea to treat non-GC DB interactions as "readers" and rely on LiteDB's thread-safety. – Ungoliant Jul 27 '23 at 18:39
  • It obviously _is_ wrong somewhere. Whether that's due to the specific implementation or design would be answerable by seeing code. Maybe it's just a glitch, maybe you are using the wrong tool (which I think you do, but cannot know). – Fildor Jul 28 '23 at 04:14
  • Don't get me wrong: I think we can sort this out and I'd hate for this Q to gain itself some downvotes just because it lacks some code ... – Fildor Jul 28 '23 at 08:50
  • Sorry for the long time it took me to reply! I appreciate your help. I've made a new post: https://stackoverflow.com/questions/76825834/deadlocks-in-a-server-that-uses-litedb-and-asyncreaderwriterlock – Ungoliant Aug 03 '23 at 07:37
  • 1
    I would love it if you can check it out. (I will delete this one.) – Ungoliant Aug 03 '23 at 07:37

0 Answers0