bitwit / strider-scheduler

A scheduler plugin for Strider CD
5 stars 3 forks source link

Cannot read property 'format' of null #2

Closed emcniece closed 7 years ago

emcniece commented 7 years ago

Plugin is throwing an error on an invalid property read:

48 died 1 null
58 forked
events.js:160
      throw er; // Unhandled 'error' event
      ^

TypeError: Cannot read property 'format' of null
    at addBranchToSchedule (/data/node_modules/strider-scheduler/lib/scheduler.js:43:121)
    at /data/node_modules/strider-scheduler/lib/scheduler.js:23:25
    at Query.<anonymous> (/data/node_modules/mongoose/lib/model.js:3343:16)
    at /data/node_modules/kareem/index.js:259:21
    at /data/node_modules/kareem/index.js:127:16
    at _combinedTickCallback (internal/process/next_tick.js:67:7)
    at process._tickDomainCallback (internal/process/next_tick.js:122:9)

Here is the scheduledBranch dump, logged from an inserted line 42:

2016-10-16T01:31:35.881Z - info: DEBUG:  { project:
   { _id: 5802c73db030680018b01bb5,
     name: 'bot/strider-test',
     display_name: 'bot/strider-test',
     display_url: 'https://github.com/bot/strider-test',
     creator: 123456780-1234567890,
     __v: 5,
     provider:
      { id: 'github',
        account: '111111',
        repo_id: '111112',
        config: [Object] },
     branches: [ [Object], [Object] ],
     prefetch_config: true,
     public: false },
  branch:
   { active: true,
     mirror_master: false,
     deploy_on_green: true,
     deploy_on_pull_request: false,
     plugins: [ [Object], [Object] ],
     runner: { id: 'simple-runner' },
     _id: d2839f02032903i0wi0,
     privkey: '-----BEGIN RSA PRIVATE KEY-----\n\n-----END RSA PRIVATE KEY-----',
     pubkey: 'ssh-rsa/user@site.com',
     name: 'master' },
  config: { time: '2016-10-16T01:18:53.530Z', frequency: 86400000 },
  nextScheduledTime: null }

After commenting line 43, Strider started again and I attempted to change the scheduled time. On saving the new settings, Strider crashed again:

2016-10-16T01:35:42.558Z - info: [Scheduler]: First branch added, starting timer
2016-10-16T01:35:42.558Z - info: [Scheduler]: Currently 1 branches are scheduled
events.js:160
      throw er; // Unhandled 'error' event
      ^

TypeError: Cannot read property 'format' of null
    at Object.branchChange (/data/node_modules/strider-scheduler/lib/scheduler.js:155:58)
    at EventEmitter.<anonymous> (/data/node_modules/strider-scheduler/webapp.js:20:27)
    at emitMany (events.js:127:13)
    at EventEmitter.emit (events.js:201:7)
    at /opt/strider/lib/routes/index.js:124:20
    at /opt/strider/lib/middleware.js:167:7
    at /data/node_modules/mongoose/lib/model.js:3343:16
    at /data/node_modules/mongoose/lib/document.js:1947:18
    at _combinedTickCallback (internal/process/next_tick.js:67:7)
    at process._tickDomainCallback (internal/process/next_tick.js:122:9)
1405 died 1 null
1415 forked

Inserting another debug log before line 155 reveals that nextTime is null, and commenting line 155 allows Strider to run again - until the time comes for the job to be run. Then we crash again:

2016-10-16T01:40:31.481Z - info: DEBUG 2: null
/data/node_modules/strider-scheduler/lib/scheduler.js:99
          console.log('[Scheduler]: Running new job. Branch next scheduled to run at', nextTime.format());
                                                                                               ^

TypeError: Cannot read property 'format' of null
    at Timeout.checkScheduledBranches [as _onTimeout] (/data/node_modules/strider-scheduler/lib/scheduler.js:99:96)
    at ontimeout (timers.js:365:14)
    at tryOnTimeout (timers.js:237:5)
    at Timer.listOnTimeout (timers.js:207:5)
1620 died 1 null
1630 forked

Chased this through utils.js: getNextScheduledTime() is returning null. I am trying to run tasks on a daily basis, and days.length is empty. When the day checkboxes are clicked in the front-end config, $scope.isDaySelected = function (day) errors out because $scope.config.daySelection is undefined. I have added a catch in here to establish an empty array:

$scope.isDaySelected = function (day) {
  if(!$scope.config.daySelection)
    $scope.config.daySelection = [];

  for (var i = 0; i < $scope.config.daySelection.length; i++) {
    var obj = $scope.config.daySelection[i];
    if (day.value === obj.value) {
      return true;
    }
  }
};

Days are now selected properly, and $scope.config looks like this:

Object {
  daySelection:Array[1]
    0:Object
      $$hashKey:"object:154"
      key:"Tuesday"
      value:2
  frequency:86400000
  time:"2016-10-16T01:59:53.530Z"
}

Unfortunately, clicking the save button produces an error:

jquery.js:9175 PUT https://stridersite.com/limbicbot/strider-test/config/branch/scheduler/?branch=master 500 (Internal Server Error)
config.js:530 Uncaught TypeError: Cannot read property '0' of undefined

The PUT request response is simply {"error":"Failed to save plugin config"} and the config.js:530 file is the Strider $.ajax handler for save config requests. Dead ends so far.

emcniece commented 7 years ago

Funny story... I ran into this problem a while back when working on another Strider plugin: https://github.com/Strider-CD/strider-extension-loader/issues/14. I didn't even remember this until coming across that issue. Time is a weird thing.

Pretty sure that complex objects can't be stored in config options because they get mapped to single strings when they get passed through to MongoDB. This means that the daySelection array needs to be simplified.

emcniece commented 7 years ago

Ok, got it figured out. In config/config.js there are 3 updates that need to happen:

  1. $scope.toggleDaySelection should only push the day value to daySelection, not the entire day object.
  2. $scope.isDaySelected needs an empty array check before iterating
  3. $scope.isDaySelected when comparing values should compare day.value to obj directly, since the new daySelection array is values only.

PR incoming.