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

ConnectionStateListener gets overwritten by library #37

Open
keryigit opened this issue Mar 7, 2024 · 0 comments
Open

ConnectionStateListener gets overwritten by library #37

keryigit opened this issue Mar 7, 2024 · 0 comments

Comments

@keryigit
Copy link

keryigit commented Mar 7, 2024

Describe the bug
The AgvController._subscribeOnStarted method is asynchonrously overwriting user registered connection state listeners.

Is this a regression?
No

To Reproduce
Minimal steps to reproduce the behavior:

  1. Override the method AgvController.onStarted like this:
        class MyAgvController extends AgvController {
        ...
         protected async onStarted() {
            await super.onStarted()
            this.registerConnectionStateChange((st, ps) => { console.log(`connection state change ${ps} -> ${st}`) })
         }
         ...
         }
  2. Run MyAgvController.start()
  3. Wait for connection
  4. Disconnect externally (eg. disable wifi / unplug ethernet cable)
  5. Wait > 15s
  6. Reconnect externally

Expected behavior
The disconnect state change (online -> offline) should be called through our registered callback.

Environment:

  • Package Version: [1.4.0]
  • Node.js Version: [20.11.1]
  • OS: [Ubuntu 20.04]

Additional context
The problem lies in the asynchronous callback in the AgvController.attach method:

    private _attachAdapter() {
        this.debug("Invoking attach handler");
        this._agvAdapter.attach({
            attached: async initialState => { // this is an async callback
                // Ensure subscriptions on orders and instant actions are
                // registered with the broker before publishing the initial
                // state. A Master Control may observe this state to immediately
                // trigger initial instant actions or orders.
                this.updatePartialState(initialState, false);
                await this._subscribeOnStarted();
                this._publishCurrentState();
            },
        });
    }
    ...
    private async _subscribeOnStarted() {
        // First, subscribe to orders and instant actions.
        await this.subscribe(Topic.Order, order => this._processOrder(order));
        await this.subscribe(Topic.InstantActions, actions => this._processInstantActions(actions));

        // Ensure State is reported immediately once after client is online again.
        console.log(`_subscribeOnStarted register connection listener@ ${Date.now()}`);
        this.registerConnectionStateChange((currentState, prevState) => { // this is called after all subscriptions are done, which may happen AFTER onStarted has returned, and after we registered our listener
            if (currentState === "online" && prevState !== "online") {
                this._publishCurrentState();
            }
        });

        this._setupPublishVisualizationInterval();
    }

I suggest you use a second private class property to store the callback used in _subscribeOnStarted instead of the public callback.

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

No branches or pull requests

1 participant