Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add action processing queues #146

Merged
merged 58 commits into from
Sep 10, 2023
Merged

Add action processing queues #146

merged 58 commits into from
Sep 10, 2023

Conversation

VladBrok
Copy link
Contributor

@VladBrok VladBrok commented Aug 6, 2023

Closes logux/logux#54
Depends on logux/core#52 (will not work properly until logux/core#52 is merged)

This PR adds action processing queues.

A developer can specify the name of the queue for different actions and channels using Server#type and Server#channel.
If the name is not specified, the default 'main' will be used.
If a developer wants to run actions in parallel, they can add them to different queues.

Queues are created for each client, for example, if a client with id '10' creates the 'main' queue and a client with id '11' creates the 'main' queue, these would be different queues even though they have the same name, because the client ids are different.

Queues for channels and actions are always different, even if they have the same name.

if an error occurs during action processing, the queue will undo all it's other actions.

@VladBrok VladBrok marked this pull request as draft August 7, 2023 07:43
base-server/index.js Outdated Show resolved Hide resolved
base-server/index.js Outdated Show resolved Hide resolved
base-server/index.js Outdated Show resolved Hide resolved
base-server/index.js Outdated Show resolved Hide resolved
@@ -355,6 +369,45 @@ export class BaseServer {
this.listenNotes = {}
bindBackendProxy(this)

let end = (meta, queue, queueKey, ...args) => {
this.actionToQueue.delete(meta.id)
if (queue?.length() === 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why queue can be missed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question, it should never be missed at this point, but it was.

The issue was that inside on('processed'), I determine whether an action belongs to the queue by using actionToQueue map.
I save an action to this map by meta.id, but inside on('processed') I lookup the map by meta.id and action.id (because I may catch logux/undo, which has different meta.id but might have action.id of some action in the queue, in which case I need to undo all other actions in that queue).

However, after processing, I always deleted an action from the actionToQueue by meta.id, so if it was logux/undo action, the following happened:

  1. on('processed') got logux/undo with action.id = '1' and meta.id = '2'
  2. actionToQueue has an action with meta.id = '1' equal to action.id = '1' so we process logux/undo
  3. we undo all remaining actions in this queue and clear the queue
  4. we try to delete this action (logux/undo) from the actionToQueue map by meta.id = '2' and delete nothing
  5. the queue is deleted because it is empty (all actions are undone and removed from it)
  6. on('processed') got some other action with meta.id = '1'
  7. actionToQueue has an action with meta.id = '1' so we process it
  8. we try to use the queue which was deleted in step 5

Instead, in step 4 we should have deleted an action from actionToQueue using action.id so that in step 7 an action would be ignored because it was undone.

base-server/index.js Outdated Show resolved Hide resolved
end(meta.id, queue, queueKey, e)
})
this.on('processed', (action, meta) => {
let queueKey = this.actionToQueue.get(action?.id)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can’t check action.id until you check action.type. Diferent actions could have a very dfferent data in action with possible collisions.

So add logux/processed or something here. But I think we should check meta.id to mark tasks as processed on their own processed event, not on processed event of logux/processed action for that action.

@ai ai merged commit ae49d1b into logux:next Sep 10, 2023
2 checks passed
ai added a commit that referenced this pull request Oct 8, 2023
* add queues

* fix some tests

* comment out broken tests

* remove unused commented code

* remove TODO

* comment out one more test because it is failing

* fix one test

* fix one more test

* fix one more test

* fix one more test

* remove commented code

* fix bind-backend-proxy test by adding setQueue method

* fix one more test

* use setQueue inside base-server

* add type for onActions callback

* add type and docs for setQueue

* add types and docs for #type and #channel

* fix pnpm-lock

* remove eslint-disable-no-console

* change test delay

* change test delay

* change test delay

* fix test

* always unbind error if processed

* fix tests, add test

* add test

* make sure that all actions are processed before destroy

* import actionsCallback type from core

* add test that checks channel regex

* add test that checks channel pattern

* add test to check that error in one queue does not affect another queue

* add test: "undoes all other actions in a queue if some action should be undone"

* add test that checks setQueue method

* remove empty queues from the map

* replace ignoreDestroying with actionsInQueue set

* update onActions

* check for duplicate meta.id

* rename onActions to onSync

* refactor (rename, simplify code), use VladBrok/core

* optimize by binding single event listeners for all queues instead of for each action

* adjust logic when queue is undefined

* add test to check that an action with same ID is not added to the queue

* Update base-server/index.js

Co-authored-by: Andrey Sitnik <[email protected]>

* Update base-server/index.js

Co-authored-by: Andrey Sitnik <[email protected]>

* Update base-server/index.js

Co-authored-by: Andrey Sitnik <[email protected]>

* code style fix

* fix lint error

* fix missing queue

* use updated onSync api that allows to call access in a queue

* update VladBrok/core

* fix test

* fix test

* use only action.id in on(processed) for queues, fix destroying logic

* remove setQueue, change tests accordingly

* check action.type before checking action.id

* rename onSync to onReceive

---------

Co-authored-by: Andrey Sitnik <[email protected]>
ai added a commit that referenced this pull request Feb 10, 2024
* add queues

* fix some tests

* comment out broken tests

* remove unused commented code

* remove TODO

* comment out one more test because it is failing

* fix one test

* fix one more test

* fix one more test

* fix one more test

* remove commented code

* fix bind-backend-proxy test by adding setQueue method

* fix one more test

* use setQueue inside base-server

* add type for onActions callback

* add type and docs for setQueue

* add types and docs for #type and #channel

* fix pnpm-lock

* remove eslint-disable-no-console

* change test delay

* change test delay

* change test delay

* fix test

* always unbind error if processed

* fix tests, add test

* add test

* make sure that all actions are processed before destroy

* import actionsCallback type from core

* add test that checks channel regex

* add test that checks channel pattern

* add test to check that error in one queue does not affect another queue

* add test: "undoes all other actions in a queue if some action should be undone"

* add test that checks setQueue method

* remove empty queues from the map

* replace ignoreDestroying with actionsInQueue set

* update onActions

* check for duplicate meta.id

* rename onActions to onSync

* refactor (rename, simplify code), use VladBrok/core

* optimize by binding single event listeners for all queues instead of for each action

* adjust logic when queue is undefined

* add test to check that an action with same ID is not added to the queue

* Update base-server/index.js

Co-authored-by: Andrey Sitnik <[email protected]>

* Update base-server/index.js

Co-authored-by: Andrey Sitnik <[email protected]>

* Update base-server/index.js

Co-authored-by: Andrey Sitnik <[email protected]>

* code style fix

* fix lint error

* fix missing queue

* use updated onSync api that allows to call access in a queue

* update VladBrok/core

* fix test

* fix test

* use only action.id in on(processed) for queues, fix destroying logic

* remove setQueue, change tests accordingly

* check action.type before checking action.id

* rename onSync to onReceive

---------

Co-authored-by: Andrey Sitnik <[email protected]>
ai added a commit that referenced this pull request Feb 15, 2024
* add queues

* fix some tests

* comment out broken tests

* remove unused commented code

* remove TODO

* comment out one more test because it is failing

* fix one test

* fix one more test

* fix one more test

* fix one more test

* remove commented code

* fix bind-backend-proxy test by adding setQueue method

* fix one more test

* use setQueue inside base-server

* add type for onActions callback

* add type and docs for setQueue

* add types and docs for #type and #channel

* fix pnpm-lock

* remove eslint-disable-no-console

* change test delay

* change test delay

* change test delay

* fix test

* always unbind error if processed

* fix tests, add test

* add test

* make sure that all actions are processed before destroy

* import actionsCallback type from core

* add test that checks channel regex

* add test that checks channel pattern

* add test to check that error in one queue does not affect another queue

* add test: "undoes all other actions in a queue if some action should be undone"

* add test that checks setQueue method

* remove empty queues from the map

* replace ignoreDestroying with actionsInQueue set

* update onActions

* check for duplicate meta.id

* rename onActions to onSync

* refactor (rename, simplify code), use VladBrok/core

* optimize by binding single event listeners for all queues instead of for each action

* adjust logic when queue is undefined

* add test to check that an action with same ID is not added to the queue

* Update base-server/index.js

Co-authored-by: Andrey Sitnik <[email protected]>

* Update base-server/index.js

Co-authored-by: Andrey Sitnik <[email protected]>

* Update base-server/index.js

Co-authored-by: Andrey Sitnik <[email protected]>

* code style fix

* fix lint error

* fix missing queue

* use updated onSync api that allows to call access in a queue

* update VladBrok/core

* fix test

* fix test

* use only action.id in on(processed) for queues, fix destroying logic

* remove setQueue, change tests accordingly

* check action.type before checking action.id

* rename onSync to onReceive

---------

Co-authored-by: Andrey Sitnik <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Action processing queues
2 participants