Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove job configs #145

Merged
merged 6 commits into from
May 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,6 @@
"help_text": "Microsoft Office Client Secret.",
"default": ""
},
{
"key": "EnableStatusSync",
"display_name": "Enable User Status Sync Job",
"type": "bool",
"help_text": "When enabled, a Mattermost user's status will automatically update based on their Microsoft Calendar availability. This runs every 5 minutes.",
"default": false
},
{
"key": "EnableDailySummary",
"display_name": "Enable Daily Summary",
"type": "bool",
"help_text": "When enabled, Mattermost users will a receive a daily summary of their scheduled events in Microsoft Calendar. Users can choose when the summary will be sent to them.",
"default": false
},
{
"key": "TokenEncryptionKey",
"display_name": "At Rest Token Encryption Key",
Expand Down
12 changes: 3 additions & 9 deletions server/jobs/daily_summary_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ const dailySummaryJobInterval = mscalendar.DailySummaryJobInterval
// NewDailySummaryJob creates a RegisteredJob with the parameters specific to the DailySummaryJob
func NewDailySummaryJob() RegisteredJob {
return RegisteredJob{
id: dailySummaryJobID,
interval: dailySummaryJobInterval,
work: runDailySummaryJob,
isEnabledByConfig: isDailySummaryJobEnabled,
id: dailySummaryJobID,
interval: dailySummaryJobInterval,
work: runDailySummaryJob,
}
}

Expand All @@ -35,8 +34,3 @@ func runDailySummaryJob(env mscalendar.Env) {

env.Logger.Debugf("Daily summary job finished")
}

// isDailySummaryJobEnabled uses current config to determine whether the job is enabled.
func isDailySummaryJobEnabled(env mscalendar.Env) bool {
return env.EnableDailySummary
}
56 changes: 12 additions & 44 deletions server/jobs/job_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ type JobManager struct {
}

type RegisteredJob struct {
id string
interval time.Duration
work func(env mscalendar.Env)
isEnabledByConfig func(env mscalendar.Env) bool
id string
interval time.Duration
work func(env mscalendar.Env)
}

var scheduleFunc = func(api cluster.JobPluginAPI, id string, wait cluster.NextWaitInterval, cb func()) (io.Closer, error) {
Expand Down Expand Up @@ -58,47 +57,20 @@ func NewJobManager(papi cluster.JobPluginAPI, env mscalendar.Env) *JobManager {
// AddJob accepts a RegisteredJob, stores it, and activates it if enabled.
func (jm *JobManager) AddJob(job RegisteredJob) {
jm.registeredJobs.Store(job.id, job)
}

// OnConfigurationChange activates/deactivates jobs based on their current state, and the current plugin config.
func (jm *JobManager) OnConfigurationChange(env mscalendar.Env) error {
jm.mux.Lock()
defer jm.mux.Unlock()
jm.env = env

jm.registeredJobs.Range(func(k interface{}, v interface{}) bool {
job := v.(RegisteredJob)
enabled := (job.isEnabledByConfig == nil) || job.isEnabledByConfig(env)
_, active := jm.activeJobs.Load(job.id)

// Config is set to enable. Job is inactive, so activate the job.
if enabled && !active {
err := jm.activateJob(job)
if err != nil {
jm.env.Logger.Warnf("Error activating %s job. err=%v", job.id, err)
}
}

// Config is set to disable. Job is active, so deactivate the job.
if !enabled && active {
err := jm.deactivateJob(job)
if err != nil {
jm.env.Logger.Warnf("Error deactivating %s job. err=%v", job.id, err)
}
}

return true
})
return nil
err := jm.activateJob(job)
if err != nil {
jm.env.Logger.Warnf("Error activating %s job. %v", job.id, err)
}
}

// Close deactivates all active jobs. It is called in the plugin hook OnDeactivate.
func (jm *JobManager) Close() error {
jm.env.Logger.Debugf("Deactivating all jobs due to plugin deactivation.")
jm.activeJobs.Range(func(k interface{}, v interface{}) bool {
job := v.(*activeJob)
err := jm.deactivateJob(job.RegisteredJob)
if err != nil {
jm.env.Logger.Debugf("Failed to deactivate job: %v", err)
jm.env.Logger.Warnf("Failed to deactivate %s job: %v", job.id, err)
}
Comment on lines 67 to 74
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lieut-data We are experiencing an issue testing the cluster jobs in HA. We are testing with a fresh cloud server with --size miniHA, which spins up a cluster with two nodes.

I will be referring to the jobs as a singular "job" (cluster.Job), as all the jobs are showing the same behavior. The job activates properly on plugin activation. The successful activation message is logged by both nodes by the jm.activateJob method. The job runs its first execution with no issues. However, the job does not run again when its configured interval comes around.

Disabling the plugin results in the call to job.Close() to hang. Tracing the logs provided by this PR, the Deactivating all jobs due to plugin deactivation message is logged once (due to the node blocking on disable, and not allowing the second node to begin disabling), and does not log the debug message in jm.deactivateJob, nor the warning in this function. Therefore the job.Close() method must be blocking.

I'm not sure where to begin with debugging this. I'd like to debug locally, but I haven't set up an HA environment on my local machine. How do you advise moving forward with this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clear, this behavior was occurring before this PR. Part of the reason for this PR is to simplify the logic, to minimize the surface area for errors like the ones described above to occur.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(For anyone following this thread, see https://community-daily.mattermost.com/core/pl/auyr1cd1q7nu9ytmtb9a5fod8a for the resolution.)


return true
Expand All @@ -116,6 +88,7 @@ func (jm *JobManager) activateJob(job RegisteredJob) error {
actJob := newActiveJob(job, scheduled, context.Background())

jm.activeJobs.Store(job.id, actJob)
jm.env.Logger.Debugf("Activated %s job", job.id)
return nil
}

Expand All @@ -131,17 +104,12 @@ func (jm *JobManager) deactivateJob(job RegisteredJob) error {
if err != nil {
return err
}
jm.activeJobs.Delete(job.id)

jm.activeJobs.Delete(job.id)
jm.env.Logger.Debugf("Deactivated %s job", job.id)
return nil
}

// isJobActive checks if a job is currently active, which includes enabled jobs that are waiting to run for their first time.
func (jm *JobManager) isJobActive(id string) bool {
_, ok := jm.activeJobs.Load(id)
return ok
}

// getEnv returns the mscalendar.Env stored on the job manager
func (jm *JobManager) getEnv() mscalendar.Env {
return jm.env
Expand Down
119 changes: 0 additions & 119 deletions server/jobs/job_manager_test.go

This file was deleted.

12 changes: 3 additions & 9 deletions server/jobs/status_sync_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ const statusSyncJobID = "status_sync"
// NewStatusSyncJob creates a RegisteredJob with the parameters specific to the StatusSyncJob
func NewStatusSyncJob() RegisteredJob {
return RegisteredJob{
id: statusSyncJobID,
interval: mscalendar.StatusSyncJobInterval,
work: runSyncJob,
isEnabledByConfig: isStatusSyncJobEnabled,
id: statusSyncJobID,
interval: mscalendar.StatusSyncJobInterval,
work: runSyncJob,
}
}

Expand All @@ -31,8 +30,3 @@ func runSyncJob(env mscalendar.Env) {

env.Logger.Debugf("User status sync job finished")
}

// isStatusSyncJobEnabled uses current config to determine whether the job is enabled.
func isStatusSyncJobEnabled(env mscalendar.Env) bool {
return env.EnableStatusSync
}
5 changes: 0 additions & 5 deletions server/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,6 @@ func (p *Plugin) OnConfigurationChange() (err error) {
e.jobManager.AddJob(jobs.NewDailySummaryJob())
e.jobManager.AddJob(jobs.NewRenewJob())
}

err := e.jobManager.OnConfigurationChange(e.Env)
if err != nil {
e.Logger.Errorf("Error updating job manager with config. err=%v", err)
}
})

return nil
Expand Down