aleph_analytics 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +12 -0
 - data/app/assets/javascripts/angular/aleph.js.es6 +6 -0
 - data/app/assets/javascripts/angular/controllers/controllers.js.es6 +1 -0
 - data/app/assets/javascripts/angular/controllers/running_result/running_result_index_controller.js.es6 +56 -0
 - data/app/assets/javascripts/angular/filters/filters.js.es6 +24 -6
 - data/app/assets/javascripts/angular/services/services.js.es6 +10 -0
 - data/app/assets/stylesheets/application.css.sass +1 -0
 - data/app/assets/stylesheets/running_results.css.sass +15 -0
 - data/app/controllers/admin/base_controller.rb +11 -0
 - data/app/controllers/admin/running_results_controller.rb +33 -0
 - data/app/models/query_execution.rb +6 -1
 - data/app/models/user.rb +4 -0
 - data/app/views/layouts/application.html.haml +6 -0
 - data/app/views/queries/_results.html.haml +1 -1
 - data/app/views/results/_show.html.haml +2 -2
 - data/app/views/running_results/_index.html.haml +14 -0
 - data/app/views/running_results/_index_item.html.haml +32 -0
 - data/app/views/running_results/_index_sort_bar.html.haml +28 -0
 - data/app/views/visualizations/_show.html.haml +2 -2
 - data/config/example/redshift.yml +1 -0
 - data/config/example/table_blacklist.yml +7 -0
 - data/config/initializers/01_internalize_configurations.rb +4 -0
 - data/config/initializers/pester.rb +2 -2
 - data/config/initializers/rails_admin.rb +1 -1
 - data/config/routes.rb +5 -0
 - data/lib/csv_service.rb +4 -0
 - data/lib/redshift_pg/connection.rb +5 -1
 - data/lib/schemas/descriptor.rb +11 -1
 - data/lib/schemas/paginate.rb +1 -1
 - data/lib/tasks/karma.rake +1 -1
 - data/lib/tasks/resque.rake +22 -0
 - data/public/assets/.sprockets-manifest-61519c86aab355aa148c9e7c78293a9e.json +1 -0
 - data/public/assets/angular/{aleph.js-48037f371a59a5ffaff68fd517163d50.es6 → aleph.js-4356bfc80f5b7dd3a9c9fdfacc6c8e7b.es6} +6 -0
 - data/public/assets/angular/controllers/{controllers.js-94cb19ce7a5c88bfe6832a75a90b39d6.es6 → controllers.js-45fce398a9c2c371df9ffc32e8dbed84.es6} +1 -0
 - data/public/assets/angular/controllers/running_result/running_result_index_controller.js-ce5ccd9d6fd27d6fea0c2c775d65a664.es6 +56 -0
 - data/public/assets/angular/filters/filters.js-5d27b210896e5d5382b265ca12c96980.es6 +45 -0
 - data/public/assets/angular/services/{services.js-6225c5ea24a9082506d1932d7884b53b.es6 → services.js-855551e8fa01a9a3c05115c4c9fdf7db.es6} +10 -0
 - data/public/assets/{application-b990345b1178d3d77974c9ea035650ae.js → application-8bc9d85ca89b3c85e03f7d06948d2e87.js} +5 -5
 - data/public/assets/{application-18bf9378371fb83c5d7714ee63887d6d.css → application-b3586e5b2749cef985bebb24246f95b6.css} +1 -1
 - data/public/assets/resque_web/{application-705d1a4a22a72f773a8cd5c70ef9b284.js → application-4218536633ae4c535133fe1455d54cbc.js} +4 -4
 - metadata +20 -10
 - data/public/assets/.sprockets-manifest-ee5031d89f2eb0b53eb8eee944d985cf.json +0 -1
 - data/public/assets/angular/filters/filters.js-48cdb16fc89337e861c9f18ad57fd9bf.es6 +0 -27
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 2b835017996e863027ccbad3617742ffd680cfcd
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 567308aed9dec7a7ab5c34ef296f1ee6276d4503
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: ee415ff8e6d34fd5275000d91564a19052156b7ea456a5af370cfbd546ef5d3a27760feeeb0e122fc1ea9251efb5fe5df7ed155beee3dcfff4c4a5e24e2db32f
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 723ef552f7f7661ae409e4d1a6d1dc6cee7188666584a78462bdd9d893cbd17ba5c9476895cc93c9e7653fb106119bb4ab3baa8b614607c814f8a2e96cf76a2e
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -1,6 +1,18 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # Change Log
         
     | 
| 
       2 
2 
     | 
    
         
             
            All notable changes to this project will be documented in this file using [Semantic Versioning](http://semver.org/).
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
      
 4 
     | 
    
         
            +
            ## [0.2.0] - 2017-09-12
         
     | 
| 
      
 5 
     | 
    
         
            +
            ### Features
         
     | 
| 
      
 6 
     | 
    
         
            +
            - [Surface Running Queries](https://github.com/lumoslabs/aleph/issues/45)
         
     | 
| 
      
 7 
     | 
    
         
            +
            - [Site wide, saved filter for schema](https://github.com/lumoslabs/aleph/issues/38)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            ### Fixed
         
     | 
| 
      
 10 
     | 
    
         
            +
            - [Use trusty for travis](https://github.com/lumoslabs/aleph/issues/67)
         
     | 
| 
      
 11 
     | 
    
         
            +
            - [Display 24-hour format](https://github.com/lumoslabs/aleph/issues/53)
         
     | 
| 
      
 12 
     | 
    
         
            +
            - [Schema search should be able to handle numbers](https://github.com/lumoslabs/aleph/issues/59)
         
     | 
| 
      
 13 
     | 
    
         
            +
            - [Clean up /tmp result files when query fails](https://github.com/lumoslabs/aleph/issues/37)
         
     | 
| 
      
 14 
     | 
    
         
            +
            - [Increase schema query reties](https://github.com/lumoslabs/aleph/issues/64)
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
       4 
16 
     | 
    
         
             
            ## [0.1.0] - 2017-04-27
         
     | 
| 
       5 
17 
     | 
    
         
             
            ### Features
         
     | 
| 
       6 
18 
     | 
    
         
             
            - [Auto-complete on dot](https://github.com/lumoslabs/aleph/issues/48)
         
     | 
| 
         @@ -91,6 +91,12 @@ 
     | 
|
| 
       91 
91 
     | 
    
         
             
                      controller: 'SnippetIndexController',
         
     | 
| 
       92 
92 
     | 
    
         
             
                      controllerAs: 'snippetIdxCtrl'
         
     | 
| 
       93 
93 
     | 
    
         
             
                    })
         
     | 
| 
      
 94 
     | 
    
         
            +
                    .when('/running_results', {
         
     | 
| 
      
 95 
     | 
    
         
            +
                      title: 'RunningResults',
         
     | 
| 
      
 96 
     | 
    
         
            +
                      templateUrl: 'runningResultIndex',
         
     | 
| 
      
 97 
     | 
    
         
            +
                      controller: 'RunningResultIndexController',
         
     | 
| 
      
 98 
     | 
    
         
            +
                      controllerAs: 'runningResultsIdxCtrl'
         
     | 
| 
      
 99 
     | 
    
         
            +
                    })
         
     | 
| 
       94 
100 
     | 
    
         
             
                    .otherwise('/queries');
         
     | 
| 
       95 
101 
     | 
    
         
             
                }]);
         
     | 
| 
       96 
102 
     | 
    
         
             
            }(angular));
         
     | 
| 
         @@ -9,6 +9,7 @@ 
     | 
|
| 
       9 
9 
     | 
    
         
             
                  'alephControllers.queryReplController',
         
     | 
| 
       10 
10 
     | 
    
         
             
                  'alephControllers.alertIndexController',
         
     | 
| 
       11 
11 
     | 
    
         
             
                  'alephControllers.alertShowController',
         
     | 
| 
      
 12 
     | 
    
         
            +
                  'alephControllers.runningResultIndexController',
         
     | 
| 
       12 
13 
     | 
    
         
             
                  'alephControllers.snippetIndexController',
         
     | 
| 
       13 
14 
     | 
    
         
             
                  'alephControllers.singleResultShowController',
         
     | 
| 
       14 
15 
     | 
    
         
             
                  'alephServices',
         
     | 
| 
         @@ -0,0 +1,56 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            !(angular => {
         
     | 
| 
      
 2 
     | 
    
         
            +
              'use strict';
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              class RunningResultIndexController {
         
     | 
| 
      
 5 
     | 
    
         
            +
                constructor($scope, ModelManager, $interval) {
         
     | 
| 
      
 6 
     | 
    
         
            +
                  this._$interval = $interval;
         
     | 
| 
      
 7 
     | 
    
         
            +
                  this._runningResultModelClasses = ModelManager.forModelName('runningResult');
         
     | 
| 
      
 8 
     | 
    
         
            +
                  this._RunningResult = this._runningResultModelClasses.modelClass();
         
     | 
| 
      
 9 
     | 
    
         
            +
                  this._RunningResults = this._runningResultModelClasses.collectionClass(this._RunningResult);
         
     | 
| 
      
 10 
     | 
    
         
            +
                  this.runningResults = new this._RunningResults();
         
     | 
| 
      
 11 
     | 
    
         
            +
                  this._pollForRunningResults();
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  $scope.$on('$destroy', () => {
         
     | 
| 
      
 14 
     | 
    
         
            +
                    this._$interval.cancel(this._intervalPromises);
         
     | 
| 
      
 15 
     | 
    
         
            +
                  });
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  // angular sorting
         
     | 
| 
      
 18 
     | 
    
         
            +
                  this.initialSortDirections = { started_at: true, author: true, duration_seconds: true, query_title: false };
         
     | 
| 
      
 19 
     | 
    
         
            +
                }
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                isRepl(result) {
         
     | 
| 
      
 22 
     | 
    
         
            +
                  return !_.exists(result.item.query_id) || !_.exists(result.item.query_version_id);
         
     | 
| 
      
 23 
     | 
    
         
            +
                }
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                getType(result) {
         
     | 
| 
      
 26 
     | 
    
         
            +
                  return this.isRepl(result) ? 'REPL' : 'SAVED';
         
     | 
| 
      
 27 
     | 
    
         
            +
                }
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                setPredicate(predicate) {
         
     | 
| 
      
 30 
     | 
    
         
            +
                  if (predicate === this.predicate) {
         
     | 
| 
      
 31 
     | 
    
         
            +
                     this.reverse = !this.reverse;
         
     | 
| 
      
 32 
     | 
    
         
            +
                   } else {
         
     | 
| 
      
 33 
     | 
    
         
            +
                     this.predicate = predicate;
         
     | 
| 
      
 34 
     | 
    
         
            +
                     this.reverse = !!this.initialSortDirections[predicate];
         
     | 
| 
      
 35 
     | 
    
         
            +
                   }
         
     | 
| 
      
 36 
     | 
    
         
            +
                }
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                getPredicate() {
         
     | 
| 
      
 39 
     | 
    
         
            +
                  return 'item.' + this.predicate;
         
     | 
| 
      
 40 
     | 
    
         
            +
                }
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                // private methods
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                _pollForRunningResults() {
         
     | 
| 
      
 45 
     | 
    
         
            +
                  this.runningResults.initCollection();
         
     | 
| 
      
 46 
     | 
    
         
            +
                  this._intervalPromises = this._$interval(() => this.runningResults.initCollection(), 25000);
         
     | 
| 
      
 47 
     | 
    
         
            +
                }
         
     | 
| 
      
 48 
     | 
    
         
            +
            }
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            RunningResultIndexController.$inject = ['$scope', 'ModelManager', '$interval'];
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            angular
         
     | 
| 
      
 53 
     | 
    
         
            +
              .module('alephControllers.runningResultIndexController', ['alephServices'])
         
     | 
| 
      
 54 
     | 
    
         
            +
              .controller('RunningResultIndexController', RunningResultIndexController);
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            }(angular));
         
     | 
| 
         @@ -11,17 +11,35 @@ 
     | 
|
| 
       11 
11 
     | 
    
         
             
                })
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
                .filter('humanReadableDuration', () => {
         
     | 
| 
       14 
     | 
    
         
            -
                  return ( 
     | 
| 
      
 14 
     | 
    
         
            +
                  return (originalSeconds) => {
         
     | 
| 
       15 
15 
     | 
    
         
             
                    let SECONDS_IN_HOUR = 3600;
         
     | 
| 
       16 
16 
     | 
    
         
             
                    let SECONDS_IN_MINUTE = 60;
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                    let hours = Math.floor( 
     | 
| 
       19 
     | 
    
         
            -
                    let minutes = Math.floor(( 
     | 
| 
       20 
     | 
    
         
            -
                    let seconds = Math.round( 
     | 
| 
      
 18 
     | 
    
         
            +
                    let hours = Math.floor(originalSeconds / SECONDS_IN_HOUR);
         
     | 
| 
      
 19 
     | 
    
         
            +
                    let minutes = Math.floor((originalSeconds % SECONDS_IN_HOUR) / SECONDS_IN_MINUTE);
         
     | 
| 
      
 20 
     | 
    
         
            +
                    let seconds = Math.round(originalSeconds % SECONDS_IN_MINUTE);
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
                    return (( 
     | 
| 
       23 
     | 
    
         
            -
                           (( 
     | 
| 
      
 22 
     | 
    
         
            +
                    return ((originalSeconds > SECONDS_IN_HOUR) ? hours + ' hours ' : '') +
         
     | 
| 
      
 23 
     | 
    
         
            +
                           ((originalSeconds > SECONDS_IN_MINUTE) ? minutes + ' minutes ' : '') +
         
     | 
| 
       24 
24 
     | 
    
         
             
                           seconds + ' seconds';
         
     | 
| 
       25 
25 
     | 
    
         
             
                  };
         
     | 
| 
      
 26 
     | 
    
         
            +
                })
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                .filter('runtimeDuration', () => {
         
     | 
| 
      
 29 
     | 
    
         
            +
                  return (originalSeconds) => {
         
     | 
| 
      
 30 
     | 
    
         
            +
                    let SECONDS_IN_DAY = 86400;
         
     | 
| 
      
 31 
     | 
    
         
            +
                    let SECONDS_IN_HOUR = 3600;
         
     | 
| 
      
 32 
     | 
    
         
            +
                    let SECONDS_IN_MINUTE = 60;
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    let days = Math.floor(originalSeconds / SECONDS_IN_DAY);
         
     | 
| 
      
 35 
     | 
    
         
            +
                    let hours = Math.floor((originalSeconds % SECONDS_IN_DAY) / SECONDS_IN_HOUR);
         
     | 
| 
      
 36 
     | 
    
         
            +
                    let minutes = Math.floor((originalSeconds % SECONDS_IN_HOUR) / SECONDS_IN_MINUTE);
         
     | 
| 
      
 37 
     | 
    
         
            +
                    let seconds = Math.round(originalSeconds % SECONDS_IN_MINUTE);
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    return ((originalSeconds > SECONDS_IN_DAY) ? days + ' days ' : '') +
         
     | 
| 
      
 40 
     | 
    
         
            +
                           ((originalSeconds > SECONDS_IN_HOUR) ? hours + ':' : '00:') +
         
     | 
| 
      
 41 
     | 
    
         
            +
                           ((originalSeconds > SECONDS_IN_MINUTE) ? minutes + ':' : '00:') +
         
     | 
| 
      
 42 
     | 
    
         
            +
                           seconds;
         
     | 
| 
      
 43 
     | 
    
         
            +
                  };
         
     | 
| 
       26 
44 
     | 
    
         
             
                });
         
     | 
| 
       27 
45 
     | 
    
         
             
            }(angular));
         
     | 
| 
         @@ -105,6 +105,16 @@ 
     | 
|
| 
       105 
105 
     | 
    
         
             
                    }
         
     | 
| 
       106 
106 
     | 
    
         
             
                  },
         
     | 
| 
       107 
107 
     | 
    
         | 
| 
      
 108 
     | 
    
         
            +
                  runningResult: {
         
     | 
| 
      
 109 
     | 
    
         
            +
                    //runningResult is a read only model
         
     | 
| 
      
 110 
     | 
    
         
            +
                    // no need for newItem since no need to figure out dirty awareness
         
     | 
| 
      
 111 
     | 
    
         
            +
                    newItem: {},
         
     | 
| 
      
 112 
     | 
    
         
            +
                    resource: {
         
     | 
| 
      
 113 
     | 
    
         
            +
                      path: '/running_results/:id.json',
         
     | 
| 
      
 114 
     | 
    
         
            +
                      parameters: {id: '@id'}
         
     | 
| 
      
 115 
     | 
    
         
            +
                    }
         
     | 
| 
      
 116 
     | 
    
         
            +
                  },
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
       108 
118 
     | 
    
         
             
                  visualization: {
         
     | 
| 
       109 
119 
     | 
    
         
             
                    newItem: {
         
     | 
| 
       110 
120 
     | 
    
         
             
                      html_source: '',
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            .running-results-index
         
     | 
| 
      
 2 
     | 
    
         
            +
              .query-body-preview
         
     | 
| 
      
 3 
     | 
    
         
            +
                font-family: Menlo, Courier New, Courier
         
     | 
| 
      
 4 
     | 
    
         
            +
                font-size: 9px
         
     | 
| 
      
 5 
     | 
    
         
            +
                max-height: 100px
         
     | 
| 
      
 6 
     | 
    
         
            +
                overflow-y: auto
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              .type-tag
         
     | 
| 
      
 9 
     | 
    
         
            +
                background-color: tomato
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              .repl-tag-color
         
     | 
| 
      
 12 
     | 
    
         
            +
                background-color: #5e8eae
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              .clipboard
         
     | 
| 
      
 15 
     | 
    
         
            +
                margin-left: 14px
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Admin
         
     | 
| 
      
 2 
     | 
    
         
            +
              class RunningResultsController < BaseController
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                RUNNING_RESULTS = <<-SQL
         
     | 
| 
      
 5 
     | 
    
         
            +
                  SELECT
         
     | 
| 
      
 6 
     | 
    
         
            +
                    title query_title,
         
     | 
| 
      
 7 
     | 
    
         
            +
                    compiled_body query_body,
         
     | 
| 
      
 8 
     | 
    
         
            +
                    TO_CHAR(results.started_at, 'YYYY-MM-DD HH24:MI:SS') started_at,
         
     | 
| 
      
 9 
     | 
    
         
            +
                    ROUND(EXTRACT(EPOCH FROM (now() - results.started_at)::INTERVAL)) duration_seconds,
         
     | 
| 
      
 10 
     | 
    
         
            +
                    users.name author,
         
     | 
| 
      
 11 
     | 
    
         
            +
                    users.role author_role,
         
     | 
| 
      
 12 
     | 
    
         
            +
                    queries.id query_id,
         
     | 
| 
      
 13 
     | 
    
         
            +
                    query_versions.id AS query_version_id,
         
     | 
| 
      
 14 
     | 
    
         
            +
                    version
         
     | 
| 
      
 15 
     | 
    
         
            +
                  FROM results
         
     | 
| 
      
 16 
     | 
    
         
            +
                    LEFT OUTER JOIN query_versions ON query_versions.id = results.query_version_id
         
     | 
| 
      
 17 
     | 
    
         
            +
                    LEFT OUTER JOIN queries ON query_versions.query_id = queries.id
         
     | 
| 
      
 18 
     | 
    
         
            +
                    INNER JOIN users ON results.owner_id = users.id
         
     | 
| 
      
 19 
     | 
    
         
            +
                  WHERE results.status = 'running'
         
     | 
| 
      
 20 
     | 
    
         
            +
                SQL
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                respond_to :json
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def index
         
     | 
| 
      
 25 
     | 
    
         
            +
                  respond_to do |format|
         
     | 
| 
      
 26 
     | 
    
         
            +
                    format.html
         
     | 
| 
      
 27 
     | 
    
         
            +
                    format.json do
         
     | 
| 
      
 28 
     | 
    
         
            +
                      render json: ActiveRecord::Base.connection.exec_query(RUNNING_RESULTS)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -4,6 +4,7 @@ class QueryExecution 
     | 
|
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
              def self.perform(result_id, role)
         
     | 
| 
       6 
6 
     | 
    
         
             
                result = Result.find(result_id)
         
     | 
| 
      
 7 
     | 
    
         
            +
                csv_service = CsvService.new(result_id)
         
     | 
| 
       7 
8 
     | 
    
         | 
| 
       8 
9 
     | 
    
         
             
                unless Role.configured_connections.include?(role)
         
     | 
| 
       9 
10 
     | 
    
         
             
                  raise "Role '#{role}' does not have connection credentials configured."
         
     | 
| 
         @@ -31,9 +32,13 @@ class QueryExecution 
     | 
|
| 
       31 
32 
     | 
    
         
             
                  result.mark_complete_with_count(row_count)
         
     | 
| 
       32 
33 
     | 
    
         
             
                end
         
     | 
| 
       33 
34 
     | 
    
         
             
              rescue *RedshiftPG::USER_ERROR_CLASSES => e
         
     | 
| 
      
 35 
     | 
    
         
            +
                csv_service.clear_tmp_file
         
     | 
| 
       34 
36 
     | 
    
         
             
                result.mark_failed!(e.message)
         
     | 
| 
       35 
37 
     | 
    
         
             
              rescue => e
         
     | 
| 
       36 
     | 
    
         
            -
                result 
     | 
| 
      
 38 
     | 
    
         
            +
                if result && csv_service
         
     | 
| 
      
 39 
     | 
    
         
            +
                  csv_service.clear_tmp_file
         
     | 
| 
      
 40 
     | 
    
         
            +
                  result.mark_failed!(e.message)
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
       37 
42 
     | 
    
         
             
                raise
         
     | 
| 
       38 
43 
     | 
    
         
             
              end
         
     | 
| 
       39 
44 
     | 
    
         
             
            end
         
     | 
    
        data/app/models/user.rb
    CHANGED
    
    
| 
         @@ -38,6 +38,8 @@ 
     | 
|
| 
       38 
38 
     | 
    
         
             
                  = render partial: 'alerts/show'
         
     | 
| 
       39 
39 
     | 
    
         
             
                %script#snippetIndex{type: 'text/ng-template'}
         
     | 
| 
       40 
40 
     | 
    
         
             
                  = render partial: 'snippets/index'
         
     | 
| 
      
 41 
     | 
    
         
            +
                %script#runningResultIndex{type: 'text/ng-template'}
         
     | 
| 
      
 42 
     | 
    
         
            +
                  = render partial: 'running_results/index'
         
     | 
| 
       41 
43 
     | 
    
         
             
                %script#comments-template{type: 'text/ng-template'}
         
     | 
| 
       42 
44 
     | 
    
         
             
                  = render partial: 'queries/comments'
         
     | 
| 
       43 
45 
     | 
    
         
             
                :javascript
         
     | 
| 
         @@ -64,6 +66,10 @@ 
     | 
|
| 
       64 
66 
     | 
    
         
             
                      %a.navbar-text{href: '/schemas', 'ng-class' => "{active: pathIncludes('schemas')}"}
         
     | 
| 
       65 
67 
     | 
    
         
             
                        %span.glyphicon.glyphicon-list.glyphicons-lg.glyphicon-med
         
     | 
| 
       66 
68 
     | 
    
         
             
                         Schemas
         
     | 
| 
      
 69 
     | 
    
         
            +
                      %a.navbar-text{href: '/running_results', 'ng-class' => "{active: pathIncludes('running_results')}",
         
     | 
| 
      
 70 
     | 
    
         
            +
                                    'ng-if' => "'#{current_user.role}' == 'admin'"}
         
     | 
| 
      
 71 
     | 
    
         
            +
                        %span.glyphicon.glyphicon-plane.glyphicons-lg.glyphicon-low
         
     | 
| 
      
 72 
     | 
    
         
            +
                         Inflight
         
     | 
| 
       67 
73 
     | 
    
         
             
                      %ul.nav.navbar-nav.navbar-right
         
     | 
| 
       68 
74 
     | 
    
         
             
                        %li
         
     | 
| 
       69 
75 
     | 
    
         
             
                          - if user_signed_in?
         
     | 
| 
         @@ -11,7 +11,7 @@ 
     | 
|
| 
       11 
11 
     | 
    
         
             
                    %dd{ 'ng-bind' => 'resultsCtrl.query.item.version.version' }
         
     | 
| 
       12 
12 
     | 
    
         
             
                    %br
         
     | 
| 
       13 
13 
     | 
    
         
             
                    %dt Created:
         
     | 
| 
       14 
     | 
    
         
            -
                    %dd{ 'ng-bind' => 'resultsCtrl.query.item.version.created_at | date: "yyyy-MM-dd  
     | 
| 
      
 14 
     | 
    
         
            +
                    %dd{ 'ng-bind' => 'resultsCtrl.query.item.version.created_at | date: "yyyy-MM-dd HH:mm:ss" : "UTC"' }
         
     | 
| 
       15 
15 
     | 
    
         
             
                    %br
         
     | 
| 
       16 
16 
     | 
    
         
             
                    %dt Author:
         
     | 
| 
       17 
17 
     | 
    
         
             
                    %dd{ 'ng-bind' => 'resultsCtrl.query.item.version.author_name' }
         
     | 
| 
         @@ -9,9 +9,9 @@ 
     | 
|
| 
       9 
9 
     | 
    
         
             
              .run_duration{ 'ng-if' => 'resultCtrl.result.item.status == "complete" || resultCtrl.result.item.status == "failed"'}
         
     | 
| 
       10 
10 
     | 
    
         
             
                Status: {{resultCtrl.result.item.status | uppercase}}
         
     | 
| 
       11 
11 
     | 
    
         
             
                %br
         
     | 
| 
       12 
     | 
    
         
            -
                Started: {{resultCtrl.result.item.started_at | date: 'yyyy-MM-dd  
     | 
| 
      
 12 
     | 
    
         
            +
                Started: {{resultCtrl.result.item.started_at | date: 'yyyy-MM-dd HH:mm:ss' : 'UTC'}}
         
     | 
| 
       13 
13 
     | 
    
         
             
                %br
         
     | 
| 
       14 
     | 
    
         
            -
                Ended: {{resultCtrl.result.item.completed_at | date: 'yyyy-MM-dd  
     | 
| 
      
 14 
     | 
    
         
            +
                Ended: {{resultCtrl.result.item.completed_at | date: 'yyyy-MM-dd HH:mm:ss' : 'UTC'}}
         
     | 
| 
       15 
15 
     | 
    
         
             
                %br
         
     | 
| 
       16 
16 
     | 
    
         
             
                Run duration: {{resultCtrl.result.item.run_duration | humanReadableDuration }}
         
     | 
| 
       17 
17 
     | 
    
         
             
              %span.pull-right{ 'ng-if' => 'resultCtrl.result.item.status == "processing"' } {{resultCtrl.result.item.row_count}} rows returned so far, still processing full result and csv
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            .running-results-index
         
     | 
| 
      
 2 
     | 
    
         
            +
              .row
         
     | 
| 
      
 3 
     | 
    
         
            +
                .col-md-4
         
     | 
| 
      
 4 
     | 
    
         
            +
                  .input-group.input-group-sm
         
     | 
| 
      
 5 
     | 
    
         
            +
                    %label.input-group-addon
         
     | 
| 
      
 6 
     | 
    
         
            +
                      %i.glyphicon.glyphicon-search
         
     | 
| 
      
 7 
     | 
    
         
            +
                    %input.form-control{ 'id' => 'fulltext-search', 'ng-model' => 'searchText' }
         
     | 
| 
      
 8 
     | 
    
         
            +
              .row.top30
         
     | 
| 
      
 9 
     | 
    
         
            +
                .col-md-12.index-items
         
     | 
| 
      
 10 
     | 
    
         
            +
                  %ul
         
     | 
| 
      
 11 
     | 
    
         
            +
                    %li.item-header
         
     | 
| 
      
 12 
     | 
    
         
            +
                      = render partial: 'running_results/index_sort_bar'
         
     | 
| 
      
 13 
     | 
    
         
            +
                    %li.item-container{ 'ng-repeat' => 'result in runningResultsIdxCtrl.runningResults.collection | filter:searchText | orderBy:runningResultsIdxCtrl.getPredicate():runningResultsIdxCtrl.reverse' }
         
     | 
| 
      
 14 
     | 
    
         
            +
                      = render partial: 'running_results/index_item'
         
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            .index-item
         
     | 
| 
      
 2 
     | 
    
         
            +
              .row
         
     | 
| 
      
 3 
     | 
    
         
            +
                .col-md-1
         
     | 
| 
      
 4 
     | 
    
         
            +
                  %span.label.type-tag{ 'ng-bind' => 'runningResultsIdxCtrl.getType(result)',
         
     | 
| 
      
 5 
     | 
    
         
            +
                                        'ng-class' => "{'repl-tag-color': runningResultsIdxCtrl.isRepl(result)}"}
         
     | 
| 
      
 6 
     | 
    
         
            +
                .col-md-2
         
     | 
| 
      
 7 
     | 
    
         
            +
                  %a{ 'ng-href' => '/queries/{{result.item.query_id}}/query_versions/{{result.item.query_version_id}}',
         
     | 
| 
      
 8 
     | 
    
         
            +
                      'ng-if' => '!runningResultsIdxCtrl.isRepl(result)' }
         
     | 
| 
      
 9 
     | 
    
         
            +
                    .ellipsis{ 'ng-bind' => 'result.item.query_title' }
         
     | 
| 
      
 10 
     | 
    
         
            +
                  %span{ 'ng-if' => 'runningResultsIdxCtrl.isRepl(result)' } -
         
     | 
| 
      
 11 
     | 
    
         
            +
                .col-md-4
         
     | 
| 
      
 12 
     | 
    
         
            +
                  .row
         
     | 
| 
      
 13 
     | 
    
         
            +
                    .col-md-11.query-body-preview{ 'uib-popover' => '{{result.item.query_body}}',
         
     | 
| 
      
 14 
     | 
    
         
            +
                                                   'popover-trigger' => 'mouseenter',
         
     | 
| 
      
 15 
     | 
    
         
            +
                                                   'popover-popup-delay' => 1600,
         
     | 
| 
      
 16 
     | 
    
         
            +
                                                   'popover-placement' => 'right' }
         
     | 
| 
      
 17 
     | 
    
         
            +
                      %span{ 'ng-bind' => 'result.item.query_body'}
         
     | 
| 
      
 18 
     | 
    
         
            +
                    .col-md-1
         
     | 
| 
      
 19 
     | 
    
         
            +
                      %a.clipboard{ 'href' => '',
         
     | 
| 
      
 20 
     | 
    
         
            +
                                    'text' =>  'result.item.query_body',
         
     | 
| 
      
 21 
     | 
    
         
            +
                                    'supported' => 'supported',
         
     | 
| 
      
 22 
     | 
    
         
            +
                                    'clipboard' => '',
         
     | 
| 
      
 23 
     | 
    
         
            +
                                    'uib-tooltip' => 'Copy SQL to clipboard',
         
     | 
| 
      
 24 
     | 
    
         
            +
                                    'tooltip-popup-delay' => 1200,
         
     | 
| 
      
 25 
     | 
    
         
            +
                                    'tooltip-placement' => 'right' }
         
     | 
| 
      
 26 
     | 
    
         
            +
                        %span.glyphicon.glyphicon-copy
         
     | 
| 
      
 27 
     | 
    
         
            +
                .col-md-1
         
     | 
| 
      
 28 
     | 
    
         
            +
                  %span{ 'ng-bind' => 'result.item.author' }
         
     | 
| 
      
 29 
     | 
    
         
            +
                .col-md-2
         
     | 
| 
      
 30 
     | 
    
         
            +
                  %span{ 'ng-bind' => 'result.item.started_at' }
         
     | 
| 
      
 31 
     | 
    
         
            +
                .col-md-2
         
     | 
| 
      
 32 
     | 
    
         
            +
                  %span{ 'ng-bind' => 'result.item.duration_seconds | runtimeDuration' }
         
     | 
| 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            .sort-bar
         
     | 
| 
      
 2 
     | 
    
         
            +
              .row
         
     | 
| 
      
 3 
     | 
    
         
            +
                .col-md-1
         
     | 
| 
      
 4 
     | 
    
         
            +
                  %strong
         
     | 
| 
      
 5 
     | 
    
         
            +
                    TYPE
         
     | 
| 
      
 6 
     | 
    
         
            +
                .col-md-2
         
     | 
| 
      
 7 
     | 
    
         
            +
                  %strong
         
     | 
| 
      
 8 
     | 
    
         
            +
                    %a{ 'ng-click' => 'runningResultsIdxCtrl.setPredicate("query_title")' }
         
     | 
| 
      
 9 
     | 
    
         
            +
                      QUERY
         
     | 
| 
      
 10 
     | 
    
         
            +
                      .glyphicon.glyphicon-sort.tiny-icon
         
     | 
| 
      
 11 
     | 
    
         
            +
                .col-md-4
         
     | 
| 
      
 12 
     | 
    
         
            +
                  %strong
         
     | 
| 
      
 13 
     | 
    
         
            +
                    SQL BODY
         
     | 
| 
      
 14 
     | 
    
         
            +
                .col-md-1
         
     | 
| 
      
 15 
     | 
    
         
            +
                  %strong
         
     | 
| 
      
 16 
     | 
    
         
            +
                    %a{ 'ng-click' => 'runningResultsIdxCtrl.setPredicate("author")' }
         
     | 
| 
      
 17 
     | 
    
         
            +
                      AUTHOR
         
     | 
| 
      
 18 
     | 
    
         
            +
                      .glyphicon.glyphicon-sort.tiny-icon
         
     | 
| 
      
 19 
     | 
    
         
            +
                .col-md-2
         
     | 
| 
      
 20 
     | 
    
         
            +
                  %strong
         
     | 
| 
      
 21 
     | 
    
         
            +
                    %a{ 'ng-click' => 'runningResultsIdxCtrl.setPredicate("started_at")' }
         
     | 
| 
      
 22 
     | 
    
         
            +
                      STARTED AT
         
     | 
| 
      
 23 
     | 
    
         
            +
                      .glyphicon.glyphicon-sort.tiny-icon
         
     | 
| 
      
 24 
     | 
    
         
            +
                .col-md-2
         
     | 
| 
      
 25 
     | 
    
         
            +
                  %strong
         
     | 
| 
      
 26 
     | 
    
         
            +
                    %a{ 'ng-click' => 'runningResultsIdxCtrl.setPredicate("duration_seconds")' }
         
     | 
| 
      
 27 
     | 
    
         
            +
                      RUN TIME
         
     | 
| 
      
 28 
     | 
    
         
            +
                      .glyphicon.glyphicon-sort.tiny-icon
         
     | 
| 
         @@ -78,6 +78,6 @@ 
     | 
|
| 
       78 
78 
     | 
    
         
             
                %span{ 'ng-switch-when' => 'enqueued' }
         
     | 
| 
       79 
79 
     | 
    
         
             
                  Waiting to run.
         
     | 
| 
       80 
80 
     | 
    
         
             
                  %br
         
     | 
| 
       81 
     | 
    
         
            -
                  Enqueued at {{vizShowCtrl.sourceRenderer.latestResult().updated_at | date:'EEE yyyy-MM-dd  
     | 
| 
       82 
     | 
    
         
            -
                %span{ 'ng-switch-when' => 'running' } Running since {{vizShowCtrl.sourceRenderer.latestResult().updated_at | date:'EEE yyyy-MM-dd  
     | 
| 
      
 81 
     | 
    
         
            +
                  Enqueued at {{vizShowCtrl.sourceRenderer.latestResult().updated_at | date:'EEE yyyy-MM-dd HH:mm:ss a' : 'UTC'}}.
         
     | 
| 
      
 82 
     | 
    
         
            +
                %span{ 'ng-switch-when' => 'running' } Running since {{vizShowCtrl.sourceRenderer.latestResult().updated_at | date:'EEE yyyy-MM-dd HH:mm:ss a' : 'UTC'}}!
         
     | 
| 
       83 
83 
     | 
    
         
             
                %span{ 'ng-switch-default' => true } Unknown status: "{{vizShowCtrl.sourceRenderer.latestResult().status}}"
         
     | 
    
        data/config/example/redshift.yml
    CHANGED
    
    
| 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            a_schema:
         
     | 
| 
      
 2 
     | 
    
         
            +
              - a_blacklisted_table_for_schema_above
         
     | 
| 
      
 3 
     | 
    
         
            +
              - each_entry_is_converted_to_ruby_regexep_and_matched_against_tables
         
     | 
| 
      
 4 
     | 
    
         
            +
              - \Alets_say_i_dont_want_tables_starting_with*
         
     | 
| 
      
 5 
     | 
    
         
            +
            another_schema:
         
     | 
| 
      
 6 
     | 
    
         
            +
              - another_disliked_table
         
     | 
| 
      
 7 
     | 
    
         
            +
              - ^((?!I_dont_want_any_tables_not_containing_this).)*$
         
     | 
| 
         @@ -68,3 +68,7 @@ end 
     | 
|
| 
       68 
68 
     | 
    
         
             
            # -------------------------------------------------
         
     | 
| 
       69 
69 
     | 
    
         
             
            ATTRIBUTE_MAP = ingest.slurp('auth-attribute-map.yml')
         
     | 
| 
       70 
70 
     | 
    
         
             
            File.open(Rails.root.join('config', 'attribute-map.yml'), 'w') { |f| f.write(ATTRIBUTE_MAP.to_yaml) } if ATTRIBUTE_MAP
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
            # Schema Blacklist
         
     | 
| 
      
 73 
     | 
    
         
            +
            # -------------------------------------------------
         
     | 
| 
      
 74 
     | 
    
         
            +
            TABLE_BLACKLIST = ingest.slurp('table_blacklist.yml')
         
     | 
    
        data/config/routes.rb
    CHANGED
    
    | 
         @@ -17,12 +17,17 @@ Rails.application.routes.draw do 
     | 
|
| 
       17 
17 
     | 
    
         
             
              resources :tags, only: [:index, :create, :destroy]
         
     | 
| 
       18 
18 
     | 
    
         
             
              resources :alerts, only: [:show, :index, :create, :update, :destroy]
         
     | 
| 
       19 
19 
     | 
    
         
             
              resources :snippets, only: [:show, :index, :create, :update, :destroy]
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
       20 
21 
     | 
    
         
             
              resources :query_versions, only: :show
         
     | 
| 
       21 
22 
     | 
    
         
             
              resources :results, only: [:show, :create, :destroy]
         
     | 
| 
       22 
23 
     | 
    
         
             
              resources :visualizations, only: [:create, :update, :destroy]
         
     | 
| 
       23 
24 
     | 
    
         
             
              resources :schema_comments, only: [:create, :update, :destroy]
         
     | 
| 
       24 
25 
     | 
    
         
             
              resources :result_csvs, only: :show
         
     | 
| 
       25 
26 
     | 
    
         | 
| 
      
 27 
     | 
    
         
            +
              scope module: 'admin' do
         
     | 
| 
      
 28 
     | 
    
         
            +
                resources :running_results, only: [:index]
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
       26 
31 
     | 
    
         
             
              mount ResqueWeb::Engine => "/resque_web"
         
     | 
| 
       27 
32 
     | 
    
         | 
| 
       28 
33 
     | 
    
         
             
              root :to => 'application#index'
         
     | 
    
        data/lib/csv_service.rb
    CHANGED
    
    
| 
         @@ -12,6 +12,7 @@ module RedshiftPG 
     | 
|
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
                def initialize(config)
         
     | 
| 
       14 
14 
     | 
    
         
             
                  @config = config
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @statement_timeout = config['statement_timeout']
         
     | 
| 
       15 
16 
     | 
    
         
             
                end
         
     | 
| 
       16 
17 
     | 
    
         | 
| 
       17 
18 
     | 
    
         
             
                def reconnect_on_failure(&block)
         
     | 
| 
         @@ -28,8 +29,11 @@ module RedshiftPG 
     | 
|
| 
       28 
29 
     | 
    
         
             
                end
         
     | 
| 
       29 
30 
     | 
    
         | 
| 
       30 
31 
     | 
    
         
             
                private
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
       31 
33 
     | 
    
         
             
                def connect!
         
     | 
| 
       32 
     | 
    
         
            -
                  ::PG.connect(pg_config)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  ::PG.connect(pg_config).tap do |conn|
         
     | 
| 
      
 35 
     | 
    
         
            +
                    conn.exec("SET statement_timeout to #{@statement_timeout}") if @statement_timeout
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
       33 
37 
     | 
    
         
             
                end
         
     | 
| 
       34 
38 
     | 
    
         | 
| 
       35 
39 
     | 
    
         
             
                def pg_config
         
     | 
    
        data/lib/schemas/descriptor.rb
    CHANGED
    
    | 
         @@ -70,7 +70,7 @@ module Schemas 
     | 
|
| 
       70 
70 
     | 
    
         
             
                  end
         
     | 
| 
       71 
71 
     | 
    
         | 
| 
       72 
72 
     | 
    
         
             
                  if result
         
     | 
| 
       73 
     | 
    
         
            -
                    redis_store!(result.to_a)
         
     | 
| 
      
 73 
     | 
    
         
            +
                    redis_store!(filter_tables(result.to_a))
         
     | 
| 
       74 
74 
     | 
    
         
             
                    @cache = redis_retrieve
         
     | 
| 
       75 
75 
     | 
    
         
             
                  end
         
     | 
| 
       76 
76 
     | 
    
         
             
                end
         
     | 
| 
         @@ -81,5 +81,15 @@ module Schemas 
     | 
|
| 
       81 
81 
     | 
    
         
             
                    connection.pg_connection.exec(INFORMATION_SCHEMA_QUERY)
         
     | 
| 
       82 
82 
     | 
    
         
             
                  end
         
     | 
| 
       83 
83 
     | 
    
         
             
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                def filter_tables(schemas)
         
     | 
| 
      
 86 
     | 
    
         
            +
                  return schemas unless TABLE_BLACKLIST
         
     | 
| 
      
 87 
     | 
    
         
            +
                  
         
     | 
| 
      
 88 
     | 
    
         
            +
                  schemas.reject do |column|
         
     | 
| 
      
 89 
     | 
    
         
            +
                    schema_blacklist = TABLE_BLACKLIST[column['table_schema']]
         
     | 
| 
      
 90 
     | 
    
         
            +
                    next unless schema_blacklist
         
     | 
| 
      
 91 
     | 
    
         
            +
                    schema_blacklist.any? { |bl_item| Regexp.new(bl_item).match(column['table_name']) }
         
     | 
| 
      
 92 
     | 
    
         
            +
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
       84 
94 
     | 
    
         
             
              end
         
     | 
| 
       85 
95 
     | 
    
         
             
            end
         
     | 
    
        data/lib/schemas/paginate.rb
    CHANGED
    
    
    
        data/lib/tasks/karma.rake
    CHANGED
    
    
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            desc 'Clear pending tasks'
         
     | 
| 
      
 2 
     | 
    
         
            +
            task 'resque:clear' => :environment do
         
     | 
| 
      
 3 
     | 
    
         
            +
              queues = Resque.queues
         
     | 
| 
      
 4 
     | 
    
         
            +
              queues.each do |queue_name|
         
     | 
| 
      
 5 
     | 
    
         
            +
                puts "Clearing #{queue_name}..."
         
     | 
| 
      
 6 
     | 
    
         
            +
                Resque.redis.del "queue:#{queue_name}"
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              # in case of scheduler - doesn't break if no scheduler module is installed
         
     | 
| 
      
 10 
     | 
    
         
            +
              puts 'Clearing delayed...'
         
     | 
| 
      
 11 
     | 
    
         
            +
              Resque.redis.keys('delayed:*').each do |key|
         
     | 
| 
      
 12 
     | 
    
         
            +
                Resque.redis.del "#{key}"
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
              Resque.redis.del 'delayed_queue_schedule'
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              puts 'Clearing failed jobs ... '
         
     | 
| 
      
 17 
     | 
    
         
            +
              Resque::Failure.clear
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              puts 'Clearing stats...'
         
     | 
| 
      
 20 
     | 
    
         
            +
              Resque.redis.set 'stat:failed', 0
         
     | 
| 
      
 21 
     | 
    
         
            +
              Resque.redis.set 'stat:processed', 0
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     |