func (r *RPCServer) ExecutionDone(execution Execution, reply *serf.NodeResponse) error { log.WithFields(logrus.Fields{ "group": execution.Group, "job": execution.JobName, }).Debug("rpc: Received execution done") // Save job status job, err := r.agent.store.GetJob(execution.JobName) if err != nil { if err == store.ErrKeyNotFound { log.Warning(ErrExecutionDoneForDeletedJob) return ErrExecutionDoneForDeletedJob } log.Fatal("rpc:", err) return err } // Save the new execution to store if _, err := r.agent.store.SetExecution(&execution); err != nil { return err } if execution.Success { job.LastSuccess = execution.FinishedAt job.SuccessCount = job.SuccessCount + 1 } else { job.LastError = execution.FinishedAt job.ErrorCount = job.ErrorCount + 1 } if err := r.agent.store.SetJob(job); err != nil { log.Fatal("rpc:", err) } exg, err := r.agent.store.GetExecutionGroup(&execution) if err != nil { log.WithFields(logrus.Fields{ "group": execution.Group, "err": err, }).Error("rpc: Error getting execution group.") return err } // Send notification Notification(r.agent.config, &execution, exg).Send() reply.From = r.agent.config.NodeName reply.Payload = []byte("saved") return nil }
func (rpcs *RPCServer) ExecutionDone(execution Execution, reply *serf.NodeResponse) error { log.WithFields(logrus.Fields{ "group": execution.Group, "job": execution.JobName, }).Debug("rpc: Received execution done") // Load the job from the store job, err := rpcs.agent.store.GetJob(execution.JobName) if err != nil { if err == store.ErrKeyNotFound { log.Warning(ErrExecutionDoneForDeletedJob) return ErrExecutionDoneForDeletedJob } log.Fatal("rpc:", err) return err } // Lock the job while editing if err = job.Lock(); err != nil { log.Fatal("rpc:", err) } // Get the defined output types for the job, and call them origExec := execution for k, v := range job.Processors { log.WithField("plugin", k).Debug("rpc: Processing execution with plugin") processor := rpcs.agent.ProcessorPlugins[k] e := processor.Process(&ExecutionProcessorArgs{Execution: origExec, Config: v}) execution = e } // Save the execution to store if _, err := rpcs.agent.store.SetExecution(&execution); err != nil { return err } if execution.Success { job.LastSuccess = execution.FinishedAt job.SuccessCount++ } else { job.LastError = execution.FinishedAt job.ErrorCount++ } if err := rpcs.agent.store.SetJob(job); err != nil { log.Fatal("rpc:", err) } // Release the lock if err = job.Unlock(); err != nil { log.Fatal("rpc:", err) } reply.From = rpcs.agent.config.NodeName reply.Payload = []byte("saved") // If the execution failed, retry it until retries limit (default: don't retry) if !execution.Success && execution.Attempt < job.Retries+1 { execution.Attempt++ log.WithFields(logrus.Fields{ "attempt": execution.Attempt, "execution": execution, }).Debug("Retrying execution") rpcs.agent.RunQuery(&execution) return nil } exg, err := rpcs.agent.store.GetExecutionGroup(&execution) if err != nil { log.WithError(err).WithField("group", execution.Group).Error("rpc: Error getting execution group.") return err } // Send notification Notification(rpcs.agent.config, &execution, exg, job).Send() // Jobs that have dependent jobs are a bit more expensive because we need to call the Status() method for every execution. // Check first if there's dependent jobs and then check for the job status to begin executiong dependent jobs on success. if len(job.DependentJobs) > 0 && job.Status() == Success { for _, djn := range job.DependentJobs { dj, err := rpcs.agent.store.GetJob(djn) if err != nil { return err } dj.Run() } } return nil }