acebase icon indicating copy to clipboard operation
acebase copied to clipboard

Live query and indexing

Open TELECI-PROJECT opened this issue 2 years ago • 8 comments

Hi! I’m facing the following issue. It seems it is related to live queries and index updates. I did some testing, my setup was working well when indexing by keys that are not included as parameters in live queries.

As I indexed my data by key/keys included in a live query my node script started

This is my system setup: [email protected] [email protected] [email protected]

This is what works well: I have data objects stored in ‘items’ folder, each one has unique ID. Item/uniqueid/{category: category1, location: location1, status: 1} Item/uniqueid/{category: category2, location: location1, status: 3} Item/uniqueid/{..} Etc.

Then I have two indexes set up: Index(‘item’, ‘category’); Index(‘item’, ‘location);

Also, I have a running a live query listening to changes on ‘status’ property (on my app client).

I’m adding new items, then updating them (status is updated) and later some items are removed. Data removal is done periodically (every 10min). All updates are done sequentially.

This is what not working well: I have the same setup as above:

The difference is: now I have added an index: Index(‘item’, ‘status); I still have a running live query listening to changes on ‘status’ property as before (on my app client). This works well until the data removal script has started to remove items.

Now I see the following error and node script restarts: /loc1/xxx/xxxx/nodejs/node_modules/acebase-client/dist/cjs/request/index.js:89 reject(new error_1.AceBaseRequestError(request, null, err.code || err.name, err.message)); ^

AceBaseRequestError: connect ECONNRESET XXXXXXXXXXXXXXXXXXX:1234 at ClientRequest. (/loc1/xxx/xxxx/nodejs/node_modules/acebase-client/dist/cjs/request/index.js:89:20) at ClientRequest.emit (node:events:390:28) at TLSSocket.socketErrorListener (node:_http_client:447:9) at TLSSocket.emit (node:events:390:28) at emitErrorNT (node:internal/streams/destroy:157:8) at emitErrorCloseNT (node:internal/streams/destroy:122:3) at processTicksAndRejections (node:internal/process/task_queues:83:21) { request: { method: 'PUT', protocol: 'https:', host: 'xxxxxxxxx', port: '1234', path: '/data/acebase_test/items/1197171', headers: { 'AceBase-Context': '{"skipProcess":true,"acebase_mutation":{"client_id":"xxxxxxxxx","id":"xxxxxxxxxxxxx","op":"set","path":"items/1197171","flow":"server"}}', 'Content-Type': 'application/json', 'Content-Length': 12, Authorization: 'Bearer xxxxxxxxxx==' }, body: undefined }, response: null, code: 'ECONNRESET' }

I don’t see any errors when my data removal script is disabled. It seems deletion process interferes with the index. The index (on status key) gets corrupted and I have to recreate it. I have tried deleting data items using delete query as well.

TELECI-PROJECT avatar May 06 '23 11:05 TELECI-PROJECT

Thanks for reporting, I'll dive into it asap!

appy-one avatar May 08 '23 14:05 appy-one

Thanks, I did some more testing. I was able to catch another error.

The setup is the same as above:

  1. I have an index on 'status' running,
  2. Live query is running as before,
  3. Then I update (status value changes) /items/itemd/{ status: other status value }

This corrupts 'status' index and I see this error message:

Lock "./acebase_xxxxxxx3v_2.acebase/items-status.idx" timed out! lock.release() was not called in a timely fashion [32m[acebase_xxxxxxx3v_2][39m failed to set "items/1278796": Error: Could not achieve lock because the current lock ("./acebase_xxxxxxx3v_2.acebase/items-status.idx") was not released in time (and lock is flagged critical) at /loc1/yyy/ccccc3/nodejs/node_modules/acebase/dist/cjs/thread-safe.js:52:33 at Array.forEach () at Timeout.timeoutHandler [as _onTimeout] (/home/yyy/ccccc3/nodejs/node_modules/acebase/dist/cjs/thread-safe.js:50:29) at listOnTimeout (node:internal/timers:571:11) at process.processTimers (node:internal/timers:512:7) /loc1/yyy/ccccc3/nodejs/node_modules/acebase-client/dist/cjs/request/index.js:84 return reject(new error_1.AceBaseRequestError(request, response, code, message));

TELECI-PROJECT avatar May 09 '23 10:05 TELECI-PROJECT

@TELECI-PROJECT I managed to reproduce the issue, looking into it now

appy-one avatar May 18 '23 09:05 appy-one

I spent the entire day on this issue, I am pretty sure #226 fixes it! The fix has been published with v1.28.6, let me know if it works!

appy-one avatar May 18 '23 17:05 appy-one

Hi, thanks, I don't see any errors anymore.

What I noticed is there is an issue with the live query events emission.

When index on 'status' is enabled, live query is not emitting 'change' events. It seems 'remove' events are working fine. (I don't use 'add' event).

Everything works fine when there is no index on 'status'.

TELECI-PROJECT avatar May 20 '23 08:05 TELECI-PROJECT

Are you sure this is not the right behavior? If you have a query with a filter on status == 1, and the status changes to 2, this will cause a remove event on your query because it does not meet the filter requirement. If you change any other field that is in the result set of your query (and still meets any filter requirements) that should emit change events.

The fact that you mention in works differently without the index in place does require further investigation on my end though! It would be helpful if you can submit minimal code that reproduces it and demonstrates this faulty behavior, that would save me a lot of time trying to reproduce it. You can use my test code created for this issue as boilerplate code if that helps: https://github.com/appy-one/acebase/blob/master/src/test/issue-225.spec.ts

appy-one avatar May 20 '23 09:05 appy-one

Ok, I will think of the code reproduction soon.

It seems I was wrong about remove event.

I have two live queries, one is listening to status == 1, the other is listening to status == 2. (events on CHANGE and on REMOVE).

Test 1: Index 'status' is enabled: my live query is firing no events.

Test 2: No 'status' index enabled: my live query is firing events (CHANGE and REMOVE)

TELECI-PROJECT avatar May 20 '23 10:05 TELECI-PROJECT

Hi, please find information about my tests below:

This is the test code was using: https://github.com/TELECI-PROJECT/acebase-testing/blob/main/testing-live-query-and-indexing (this is based on your test code https://github.com/appy-one/acebase/blob/master/src/test/issue-225.spec.ts)

I was running it on Nodejs v18.14.0. This is my setup: [email protected] [email protected] [email protected]

The database folder was removed for every test.

Testing results:

TEST 1 I was running the code with all tree indexes: await db.indexes.create('items', 'location'); await db.indexes.create('items', 'category'); await db.indexes.create('items', 'status');

There were no events fired by Acebase live query Test result: 0 added, 0 changed, 0 removed

TEST 2 I was running the code with one index: await db.indexes.create('items', 'location'); //await db.indexes.create('items', 'category'); //await db.indexes.create('items', 'status');

Acebase live query was firing events as expected Test result: 1000 added, 144 changed, 1000 removed

Conclusion: Acebase live query is firing events as expected if none of query filter parameters is indexed. In this case they are params ‘category’ and ‘status’. The live query won’t fire events if any of filter parameters is indexed.

The following two test scenario won’t work either (meaning the live query won’t emit any events): await db.indexes.create('items', 'location'); await db.indexes.create('items', 'category'); //await db.indexes.create('items', 'status');

OR await db.indexes.create('items', 'location'); //await db.indexes.create('items', 'category'); await db.indexes.create('items', 'status');

TELECI-PROJECT avatar Jun 03 '23 07:06 TELECI-PROJECT