<commit_before>angular.module(PKG.name+'.services')
  /*
    MyDataSource // usage in a controler:

    var dataSrc = new MyDataSource($scope);

    // polling a namespaced resource example:
    dataSrc.poll({
        method: 'GET',
        _cdapNsPath: '/foo/bar'
      },
      function(result) {
        $scope.foo = result;
      }
    ); // will poll <host>:<port>/v3/namespaces/<currentNamespace>/foo/bar

    // posting to a systemwide resource:
    dataSrc.request({
        method: 'POST',
        _cdapPath: '/system/config',
        body: {
          foo: 'bar'
        }
      },
      function(result) {
        $scope.foo = result;
      }
    ); // will post to <host>:<port>/v3/system/config
   */
  .factory('MyDataSource', function ($state, $log, $rootScope, caskWindowManager, mySocket,
    MYSOCKET_EVENT, $q) {

    var instances = {}; // keyed by scopeid

    function _pollStart (resource) {
      mySocket.send({
        action: 'poll-start',
        resource: resource
      });
    }

    function _pollStop (resource) {
      mySocket.send({
        action: 'poll-stop',
        resource: resource
      });
    }

    $rootScope.$on(MYSOCKET_EVENT.reconnected, function () {
      $log.log('[DataSource] reconnected, reloading...');

      // https://github.com/angular-ui/ui-router/issues/582
      $state.transitionTo($state.current, $state.$current.params,
        { reload: true, inherit: true, notify: true }
      );
    });

    function DataSource (scope) {
      scope = scope || $rootScope.$new();

      var id = scope.$id,
          self = this;

      if(instances[id]) {
        throw new Error('multiple DataSource for scope', id);
      }
      instances[id] = self;

      this.bindings = [];

      scope.$on(MYSOCKET_EVENT.message, function (event, data) {
        if(data.statusCode>299 || data.warning) {
          angular.forEach(self.bindings, function (b) {
            if(angular.equals(b.resource, data.resource)) {
              if(b.errorCallback) {
                scope.$apply(b.errorCallback.bind(null, data));
              }
            }
          });
          return; // errors are handled at $rootScope level
        }
        angular.forEach(self.bindings, function (b) {
          if(angular.equals(b.resource, data.resource)) {
            scope.$apply(b.callback.bind(null, data.response));
          }
        });
      });

      scope.$on('$destroy', function () {
        delete instances[id];
      });

      scope.$on(caskWindowManager.event.blur, function () {
        angular.forEach(self.bindings, function (b) {
          if(b.poll) {
            _pollStop(b.resource);
          }
        });
      });

      scope.$on(caskWindowManager.event.focus, function () {
        angular.forEach(self.bindings, function (b) {
          if(b.poll) {
            _pollStart(b.resource);
          }
        });
      });

      this.scope = scope;
    }



    /**
     * poll a resource
     */
    DataSource.prototype.poll = function (resource, cb, errorCb) {
      this.bindings.push({
        poll: true,
        resource: resource,
        callback: cb,
        errorCallback: errorCb
      });

      this.scope.$on('$destroy', function () {
        _pollStop(resource);
      });

      _pollStart(resource);
    };




    /**
     * fetch a resource
     */
    DataSource.prototype.request = function (resource, cb) {
      var once = false,
          deferred = $q.defer();

      this.bindings.push({
        resource: resource,
        callback: function (result) {
          if(!once) {
            once = true;
            /*jshint -W030 */
            cb && cb.apply(this, arguments);
            deferred.resolve(result);
          }
        },
        errorCallback: function (err) {
          if(!once) {
            once = true;
            deferred.reject(err);
          }
        }
      });

      mySocket.send({
        action: 'request',
        resource: resource
      });<commit_msg>Adds the ability in MyDataSource service to stop a polling<commit_after>angular.module(PKG.name+'.services')
  /*
    MyDataSource // usage in a controler:

    var dataSrc = new MyDataSource($scope);

    // polling a namespaced resource example:
    dataSrc.poll({
        method: 'GET',
        _cdapNsPath: '/foo/bar'
      },
      function(result) {
        $scope.foo = result;
      }
    ); // will poll <host>:<port>/v3/namespaces/<currentNamespace>/foo/bar

    // posting to a systemwide resource:
    dataSrc.request({
        method: 'POST',
        _cdapPath: '/system/config',
        body: {
          foo: 'bar'
        }
      },
      function(result) {
        $scope.foo = result;
      }
    ); // will post to <host>:<port>/v3/system/config
   */
  .factory('MyDataSource', function ($state, $log, $rootScope, caskWindowManager, mySocket,
    MYSOCKET_EVENT, $q, $filter) {

    var instances = {}; // keyed by scopeid

    function _pollStart (resource) {
      mySocket.send({
        action: 'poll-start',
        resource: resource
      });
    }

    function _pollStop (resource) {
      mySocket.send({
        action: 'poll-stop',
        resource: resource
      });
    }

    $rootScope.$on(MYSOCKET_EVENT.reconnected, function () {
      $log.log('[DataSource] reconnected, reloading...');

      // https://github.com/angular-ui/ui-router/issues/582
      $state.transitionTo($state.current, $state.$current.params,
        { reload: true, inherit: true, notify: true }
      );
    });

    function DataSource (scope) {
      scope = scope || $rootScope.$new();

      var id = scope.$id,
          self = this;

      if(instances[id]) {
        throw new Error('multiple DataSource for scope', id);
      }
      instances[id] = self;

      this.bindings = [];

      scope.$on(MYSOCKET_EVENT.message, function (event, data) {
        if(data.statusCode>299 || data.warning) {
          angular.forEach(self.bindings, function (b) {
            if(angular.equals(b.resource, data.resource)) {
              if(b.errorCallback) {
                scope.$apply(b.errorCallback.bind(null, data));
              }
            }
          });
          return; // errors are handled at $rootScope level
        }
        angular.forEach(self.bindings, function (b) {
          if(angular.equals(b.resource, data.resource)) {
            scope.$apply(b.callback.bind(null, data.response));
          }
        });
      });

      scope.$on('$destroy', function () {
        delete instances[id];
      });

      scope.$on(caskWindowManager.event.blur, function () {
        angular.forEach(self.bindings, function (b) {
          if(b.poll) {
            _pollStop(b.resource);
          }
        });
      });

      scope.$on(caskWindowManager.event.focus, function () {
        angular.forEach(self.bindings, function (b) {
          if(b.poll) {
            _pollStart(b.resource);
          }
        });
      });

      this.scope = scope;
    }



    /**
     * poll a resource
     */
    DataSource.prototype.poll = function (resource, cb, errorCb) {
      // Very fundamental (naive) unique id. Wouldn't
      // work on a cluster environment if two browser sessions
      // access the same metric from different computers
      var id = Date.now();
      this.bindings.push({
        poll: true,
        resource: resource,
        id: id,
        callback: cb,
        errorCallback: errorCb
      });
      resource.id = id;

      this.scope.$on('$destroy', function () {
        _pollStop(resource);
      });

      _pollStart(resource);
      return id;
    };


    DataSource.prototype.stopPoll = function(id) {
      var filterFilter = $filter('filter');
      var match = filterFilter(this.bindings, {id: id});

      if (match.length) {
        _pollStop(match[0].resource);
        this.bindings.splice(this.bindings.indexOf(match[0]), 1);
      }
    };

    /**
     * fetch a resource
     */
    DataSource.prototype.request = function (resource, cb) {
      var once = false,
          deferred = $q.defer();

      this.bindings.push({
        resource: resource,
        callback: function (result) {
          if(!once) {
            once = true;
            /*jshint -W030 */
            cb && cb.apply(this, arguments);
            deferred.resolve(result);
          }
        },
        errorCallback: function (err) {
          if(!once) {
            once = true;
            deferred.reject(err);
          }
        }
      });

      mySocket.send({
        action: 'request',
        resource: resource
      });
{'fraction_non_alphanumeric': 0.14077613331779512, 'fraction_numerical': 0.00291341335508682, 'mean_word_length': 1.7818476499189628, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 2, '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': '3616023', 'n_tokens_mistral': 2564, 'n_tokens_neox': 2487, 'n_words': 496}