voryx / thruway.js

RxJS WAMPv2 Client
MIT License
28 stars 13 forks source link

Connection events #11

Open 27leaves opened 7 years ago

27leaves commented 7 years ago

I'd need to get some connection state events, like in autobahn with onopen and onclose. Is this already possible with thruway?

davidwdan commented 7 years ago

I haven't exposed open and close` because I haven't needed it yet and I'm not sure what the best way to expose it is. Thruway.js won't register or subscribe until the connection is established and if the connection resets, it'll reregister and resubscribe.

What is your use case?

27leaves commented 7 years ago

My use cases are

  1. Tell the user when the app is offline (like, when his internet connection is down he should reconnect, else his actions have no effect
  2. On authorization, the connection will be closed when the token is invalid. In that case I want to be able to react to that.
27leaves commented 7 years ago

Hi @davidwdan! Just wanted to check your thoughts on this feature :)

davidwdan commented 7 years ago

@creat-or If a connection is closed because of an invalid token, that error should flow through to any of the subscribers on call, topic or register, so you should also be able to handle it there.

The options for connection events are:

  1. Pass a subject into the client constructor for onOpen, onClose, and onError
  2. Expose onOpen, onClose, and onError as methods on the client that return an observable

onError will only emit errors that occur before the session is established, like transport level errors and abort messages.

davidwdan commented 6 years ago

@creat-or with the latest version you can now subscribe on open and close events:

    const ws = new WebSocketTransport("ws://127.0.0.1:9090");
    const wamp = new Client(ws, "realm1");

    ws.onOpen.subscribe(e=>console.log('open', e));
    ws.onClose.subscribe(e=>console.log('close', e));

Can you let me know if that works for you?

27leaves commented 6 years ago

@davidwdan I'm sorry that it took that long to try the feature, I haven't worked on the project since then. In my usecase I have the following code


@Injectable()
export class WampService extends Client {

  constructor(private store: Store<fromAuth.State>) {
    super(
      (environment.production) ?
        'wss://' + location.host + '/router/' :
        'wss://myserver.com/router/',
      'gateway', {
      authmethods: ['ticket']
    });

    this.onChallenge(challenge => {
      // challenge logic
    });

    this.onOpen.subscribe(e=>console.log('log:open', e));
    this.onClose.subscribe(e=>console.log('log:close', e));
  }
}

onOpen works as expected, but onClose doesn't.

As you can see, I tried to bind to the onOpen & onClose sessions of the Client instead of the WebSocketTransport. That's because Typescript doesn't allow me to add anything before the super statement. I'm not sure if the onClose just works directly on the transport.

27leaves commented 6 years ago

Hi David, just wanted to check if you could help me with my latest issue. I was busy with other projects meanwhile, but now I could use some help again ;) Thanks!

27leaves commented 6 years ago

So, I got it to work. I had to handle the instantiation of the client myself to get to the WS events. This wasn't clear for me, so maybe we should update the documentation. If you need help with this I could help :)

Here is my working code:

@Injectable()
export class WampProvider {
  private ws: WebSocketTransport<any>;
  private client: Client;

  constructor(private store: Store<fromRoot.State>) {
    this.ws = new WebSocketTransport(
      localStorage.getItem('WAMP_URL') || SERVER_CONFIG[0].url,
      undefined,
      true
    );

    this.client = new Client(this.ws, 'gateway', { authmethods: ['ticket'] });

    this.client.onChallenge(challenge => {
      const ticketMethod = challenge.filter(msg => msg.authMethod === 'ticket');

      const token = this.store
        .select(fromRoot.getUser)
        .take(1)
        .map(user => user.token);

      return ticketMethod.mergeMapTo(token);
    });

    this.ws.onOpen.subscribe(event => {
      console.log('%c WampService: Connection Opened', 'color: #32db64');
      console.log(event);
      store.dispatch(new wamp.ConnectionOpen((event as any).details));
    });
    this.ws.onClose.subscribe(error => {
      console.log('%c WampService: Connection Closed(transport)', 'color: #f53d3d');
      console.log(error);
      store.dispatch(new wamp.ConnectionClose(error));
    });
    this.client.onClose.subscribe(error => {
      console.log('%c WampService: Connection Closed(client)', 'color: #f53d3d');
      console.log(error);
      store.dispatch(new wamp.ConnectionClose(error));
    })

    // As a workaround for https://github.com/voryx/thruway.js/issues/10.
    // This is still needed when I don't extend and inject the client via Angular,
    // but handle the instantiation myself with new Client(...).
    this.client.topic('cloud.connection.created').subscribe(); 
  }

  call(
    uri: string,
    args?: Array<any>,
    argskw?: Object,
    options?: CallOptions
  ): Observable<ResultMessage> {
    return this.client.call(uri, args, argskw, options);
  }

  topic (uri: string, options?: TopicOptions): Observable<EventMessage> {
    return this.client.topic(uri, options);
  }

  close() {
    this.client.close();
  }

  // some ngrx/store thingies, you don't have to care about them,
  // but I like that it's working ;)
  subscribeConnectedToStore(uri: string, action: string, addToResult: Object) {
    return this.client
      .topic(uri)
      .subscribe(result =>
        this.store.dispatch(
          new wamp.ReceivedEvent(action, { ...result.argskw, ...addToResult })
        )
      );
  }
}
raires commented 5 years ago

Is there any way to close the socket once open?

open() { this.ws.open(); }

Then call an uri (fine up to this point. But when I try to close the connection it tries to reopen again.

this.client.close(); console result: WampService: Connection Closed(transport) wamp.ticket.O.service.ts:54 CloseEvent {isTrusted: true, wasClean: true, code: 1000, reason: "", type: "close", …} wamp.ticket.O.service.ts:54 The WebSocket connection was closed (anonymous) @ Client.js:72 Reconnecting Client.js:73 socket opened WebSocketTransport.js:82 WampService: Connection Opened wamp.ticket.O.service.ts:48 Event {isTrusted: true, type: "open", target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …} wamp.ticket.O.service.ts:49

andzejsw commented 4 years ago

Is there any way to close the socket once open?

open() { this.ws.open(); }

Then call an uri (fine up to this point. But when I try to close the connection it tries to reopen again.

this.client.close(); console result: WampService: Connection Closed(transport) wamp.ticket.O.service.ts:54 CloseEvent {isTrusted: true, wasClean: true, code: 1000, reason: "", type: "close", …} wamp.ticket.O.service.ts:54 The WebSocket connection was closed (anonymous) @ Client.js:72 Reconnecting Client.js:73 socket opened WebSocketTransport.js:82 WampService: Connection Opened wamp.ticket.O.service.ts:48 Event {isTrusted: true, type: "open", target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …} wamp.ticket.O.service.ts:49

I know this is old question, but jeah.. I just added for Client WampOptions extra option:

            retryWhen: (attempts: Observable<Error>) => Observable.of({
                maxRetries: 0,
            }),