<commit_before>import TyphonEvents  from 'backbone-common/src/TyphonEvents.js';
import Queue         from './Queue.js';
import Socket        from './Socket.js';

const DDP_VERSION = '1';

const RECONNECT_INTERVAL = 10000;

export default class DDP extends TyphonEvents
{
   constructor(options)
   {
      super();

      this.status = 'disconnected';

      this.messageQueue = new Queue((message) =>
      {
         if (this.status === 'connected') { this.socket.send(message); return true; }
         else { return false; }
      });

      this.socket = new Socket(options.SocketConstructor, options.endpoint).connect();

      this._init();
   }

   _init()
   {
      // When the socket opens, send the `connect` message to establish the DDP connection.
      this.socket.on('open', () =>
      {
         this.socket.send({ msg: 'connect', version: DDP_VERSION, support: [DDP_VERSION] });
      });

      this.socket.on('close', () =>
      {
         this.status = 'disconnected';
         this.messageQueue.empty();
         super.triggerDefer('disconnected');

         // Schedule a reconnection
         setTimeout(this.socket.connect.bind(this.socket), RECONNECT_INTERVAL);
      });

      this.socket.on('message:in', (message) =>
      {
         switch (message.msg)
         {
            case 'connected':
               this.status = 'connected';
               this.messageQueue.process();
               super.triggerDefer('connected');
               break;

            // Reply with a `pong` message to prevent the server from closing the connection.
            case 'ping':
               this.socket.send({ msg: 'pong', id: message.id });
               break;

            case 'error':
            case 'result':
            case 'updated':
               super.triggerDefer(message.msg, message);
               break;

            // Subscriptions
            case 'ready':
               // Send specific `ready` events with the subscription `id`.
               if (Array.isArray(message.subs))
               {
                  message.subs.forEach((id) => { super.triggerDefer(`sub:${message.msg}:${id}`, message); });
               }
               break;
            case 'nosub':
            case 'added':
            case 'changed':
            case 'removed':
               super.triggerDefer(message.msg, message);
               break;
         }
      });
   }

   method(name, params)
   {
      const id = s_UNIQUE_ID();

      this.messageQueue.push({ msg: 'method', id, name, params });

      return id;
   }

   sub(name, params)
   {
      const id = s_UNIQUE_ID();

      this.messageQueue.push({ msg: 'sub', id, name, params });

      return id;
   }

   unsub(id)
   {<commit_msg>Added `nosub` event / Promise resolution.<commit_after>import TyphonEvents  from 'backbone-common/src/TyphonEvents.js';
import Queue         from './Queue.js';
import Socket        from './Socket.js';

const DDP_VERSION = '1';

const RECONNECT_INTERVAL = 10000;

export default class DDP extends TyphonEvents
{
   constructor(options)
   {
      super();

      this.status = 'disconnected';

      this.messageQueue = new Queue((message) =>
      {
         if (this.status === 'connected') { this.socket.send(message); return true; }
         else { return false; }
      });

      this.socket = new Socket(options.SocketConstructor, options.endpoint).connect();

      this._init();
   }

   _init()
   {
      // When the socket opens, send the `connect` message to establish the DDP connection.
      this.socket.on('open', () =>
      {
         this.socket.send({ msg: 'connect', version: DDP_VERSION, support: [DDP_VERSION] });
      });

      this.socket.on('close', () =>
      {
         this.status = 'disconnected';
         this.messageQueue.empty();
         super.triggerDefer('disconnected');

         // Schedule a reconnection
         setTimeout(this.socket.connect.bind(this.socket), RECONNECT_INTERVAL);
      });

      this.socket.on('message:in', (message) =>
      {
         switch (message.msg)
         {
            case 'connected':
               this.status = 'connected';
               this.messageQueue.process();
               super.triggerDefer('connected');
               break;

            // Reply with a `pong` message to prevent the server from closing the connection.
            case 'ping':
               this.socket.send({ msg: 'pong', id: message.id });
               break;

            case 'error':
            case 'result':
            case 'updated':
               super.triggerDefer(message.msg, message);
               break;

            // Subscriptions
            case 'ready':
               // Send specific `ready` events with the subscription `id`.
               if (Array.isArray(message.subs))
               {
                  message.subs.forEach((id) => { super.triggerDefer(`sub:${message.msg}:${id}`, message); });
               }
               break;
            case 'nosub':
               // Send specific `nosub` events with the subscription `id`.
               if (message.id)
               {
                  super.triggerDefer(`sub:${message.msg}:${message.id}`, message);
               }
               break;
            case 'added':
            case 'changed':
            case 'removed':
               super.triggerDefer(message.msg, message);
               break;
         }
      });
   }

   method(name, params)
   {
      const id = s_UNIQUE_ID();

      this.messageQueue.push({ msg: 'method', id, name, params });

      return id;
   }

   sub(name, params)
   {
      const id = s_UNIQUE_ID();

      this.messageQueue.push({ msg: 'sub', id, name, params });

      return new Promise((resolve, reject) =>
      {
         this.once(`sub:ready:${id}`, (msg) => { this.off(`sub:nosub:${id}`); resolve(msg); }, this);
         this.once(`sub:nosub:${id}`, (msg) => { this.off(`sub:sub:${id}`); reject(msg); }, this);
      });
   }

   unsub(id)
   {
{'fraction_non_alphanumeric': 0.1388101983002833, 'fraction_numerical': 0.0019996667222129645, 'mean_word_length': 1.7544745296007342, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5035465', 'n_tokens_mistral': 1703, 'n_tokens_neox': 1661, 'n_words': 375}