// SaveResult saves a result on a job in memory func (c *Dummy) SaveResult(r *job.Result) error { c.resultsMutex.Lock() defer c.resultsMutex.Unlock() resultsKey := fmt.Sprintf(jobResultsKeyFmt, r.Job.ID) c.ResultsCounter[resultsKey]++ r.ID = c.ResultsCounter[resultsKey] results, ok := c.Results[resultsKey] if !ok { results = map[string]*job.Result{} c.Results[resultsKey] = results } results[fmt.Sprintf(resultKeyFmt, r.ID)] = r return nil }
// SaveResult stores a result of a job on boltdb func (c *BoltDB) SaveResult(r *job.Result) error { // First check if the job is present, if not, then error if _, err := c.GetJob(r.Job.ID); err != nil { return err } err := c.DB.Update(func(tx *bolt.Tx) error { resB := tx.Bucket([]byte(resultsBucket)) // Create job results bucket if doens't exist jobresKey := fmt.Sprintf(jobResultsBuckets, string(idToByte(r.Job.ID))) b, err := resB.CreateBucketIfNotExists([]byte(jobresKey)) if err != nil { return fmt.Errorf("error creating bucket: %s", err) } // Create a new ID for the new result, not new ID if it has already (update) // Starts in 1, so its safe to check with 0 if r.ID == 0 { id, _ := b.NextSequence() r.ID = int(id) } // Marshal the result buf, err := json.Marshal(r) if err != nil { return err } // Save the result return b.Put(idToByte(r.ID), buf) }) if err != nil { err = fmt.Errorf("error storing result '%d': %v", r.ID, err) logrus.Error(err.Error()) return err } logrus.Debugf("Stored result '%d' boltdb", r.ID) return nil }
func TestGetResult(t *testing.T) { j := &job.Job{ID: 1, Name: "test1", Description: "test1", When: "@daily", Active: true, URL: &url.URL{}} res3 := &job.Result{ID: 3, Job: nil, Out: "test1", Status: job.ResultInternalError, Start: time.Now().UTC(), Finish: time.Now().UTC()} testStorageClient := storage.NewDummy() testCronEngine := schedule.NewDummyCron(testConfig, testStorageClient, 0, "OK") testCronEngine.Start(nil) // Testing data tests := []struct { givenURI string givenResults map[string]map[string]*job.Result givenJobs map[string]*job.Job wantCode int wantResult *job.Result }{ { givenURI: "/api/v1/jobs/1/results/1", givenResults: make(map[string]map[string]*job.Result), givenJobs: make(map[string]*job.Job), wantCode: http.StatusInternalServerError, }, { givenURI: "/api/v1/jobs/1/results/1", givenResults: make(map[string]map[string]*job.Result), givenJobs: map[string]*job.Job{"job:1": j}, wantCode: http.StatusInternalServerError, }, { givenURI: "/api/v1/jobs/1/results/3", givenResults: map[string]map[string]*job.Result{ "job:1:results": map[string]*job.Result{ "result:1": &job.Result{ID: 1, Job: j, Out: "test1", Status: job.ResultOK, Start: time.Now().UTC(), Finish: time.Now().UTC()}, "result:2": &job.Result{ID: 2, Job: j, Out: "test1", Status: job.ResultError, Start: time.Now().UTC(), Finish: time.Now().UTC()}, "result:3": res3, // the one to check }, }, givenJobs: map[string]*job.Job{"job:1": j}, wantCode: http.StatusOK, wantResult: res3, }, } for _, test := range tests { // Set our dummy 'database' on the storage client testStorageClient.Results = test.givenResults testStorageClient.Jobs = test.givenJobs // Create a testing server testServer := server.NewSimpleServer(nil) // Register our service on the server (we don't need configuration for this service) testServer.Register(&KhronosService{ Config: testConfig, Storage: testStorageClient, Cron: testCronEngine, }) // Create request and a test recorder r, _ := http.NewRequest("GET", test.givenURI, nil) w := httptest.NewRecorder() testServer.ServeHTTP(w, r) if w.Code != test.wantCode { t.Errorf("Expected response code '%d'. Got '%d' instead ", test.wantCode, w.Code) } // Only check in good results if w.Code == http.StatusOK { b, err := ioutil.ReadAll(w.Body) if err != nil { t.Errorf("Error reading result body: %v", err) } var gotRes *job.Result if err := json.Unmarshal(b, &gotRes); err != nil { t.Errorf("Error unmarshaling: %v", err) } // Fix jobs for the deep equal gotRes.Job = nil if !reflect.DeepEqual(gotRes, test.wantResult) { t.Errorf("Expected Result '%#v'. Got '%#v' instead ", test.wantResult, gotRes) } } } }