-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
229 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package sweeper | ||
|
||
import ( | ||
"github.com/skynetlabs/pinner/logger" | ||
"sync" | ||
"time" | ||
) | ||
|
||
type ( | ||
// Status represents the status of a sweep. | ||
Status struct { | ||
InProgress bool | ||
Error error | ||
StartTime time.Time | ||
EndTime time.Time | ||
} | ||
// status is the internal status type that allows thread-safe updates. | ||
status struct { | ||
mu sync.Mutex | ||
staticLogger logger.ExtFieldLogger | ||
status Status | ||
} | ||
) | ||
|
||
// Start marks the start of a new process, unless one is already in progress. | ||
// If there is a process in progress then Start returns without any action. | ||
func (st *status) Start() { | ||
st.mu.Lock() | ||
// Double-check for parallel sweeps. | ||
if st.status.InProgress { | ||
st.mu.Unlock() | ||
st.staticLogger.Debug("Attempted to start a sweep while another one was already ongoing.") | ||
return | ||
} | ||
// Initialise the status to "a sweep is running". | ||
st.status.InProgress = true | ||
st.status.Error = nil | ||
st.status.StartTime = time.Now().UTC() | ||
st.status.EndTime = time.Time{} | ||
st.mu.Unlock() | ||
st.staticLogger.Info("Started a sweep.") | ||
} | ||
|
||
// Status returns a copy of the current status. | ||
func (st *status) Status() Status { | ||
st.mu.Lock() | ||
s := st.status | ||
st.mu.Unlock() | ||
return s | ||
} | ||
|
||
// Finalize marks a run as completed with the given error. | ||
func (st *status) Finalize(err error) { | ||
st.mu.Lock() | ||
if !st.status.InProgress { | ||
st.mu.Unlock() | ||
return | ||
} | ||
st.status.InProgress = false | ||
st.status.EndTime = time.Now().UTC() | ||
st.status.Error = err | ||
st.mu.Unlock() | ||
st.staticLogger.Info("Finalized a sweep.") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package sweeper | ||
|
||
import ( | ||
"github.com/sirupsen/logrus" | ||
"gitlab.com/NebulousLabs/errors" | ||
"io/ioutil" | ||
"testing" | ||
"time" | ||
) | ||
|
||
// TestStatus ensures the basic operation of the status type. | ||
func TestStatus(t *testing.T) { | ||
logger := logrus.New() | ||
logger.Out = ioutil.Discard | ||
|
||
s := &status{staticLogger: logger} | ||
sentinelErr := errors.New("this should not get set") | ||
|
||
// isEmpty is a helper that returns true when the given status has its zero | ||
// value. | ||
isEmpty := func(st Status) bool { | ||
return !(st.InProgress || st.Error != nil || (st.EndTime != time.Time{}) || (st.StartTime != time.Time{})) | ||
} | ||
|
||
// Check the status, expect not in progress. | ||
st := s.Status() | ||
if !isEmpty(st) { | ||
t.Fatalf("Status not empty: %+v", st) | ||
} | ||
// Try to finalize before starting, expect nothing to happen. | ||
s.Finalize(sentinelErr) | ||
st = s.Status() | ||
if !isEmpty(st) { | ||
t.Fatalf("Status not empty: %+v", st) | ||
} | ||
// Start and verify. | ||
s.Start() | ||
st = s.Status() | ||
if !st.InProgress || st.StartTime.After(time.Now().UTC()) { | ||
t.Fatalf("Unexpected status: %+v", st) | ||
} | ||
// Store the start time and verify that attempting to start again will not | ||
// change it. | ||
startTime := st.StartTime | ||
s.Start() | ||
st = s.Status() | ||
if st.StartTime != startTime { | ||
t.Fatalf("Expected start time '%s', got '%s'", startTime, st.StartTime) | ||
} | ||
// Finalize and verify. | ||
s.Finalize(sentinelErr) | ||
st = s.Status() | ||
if st.InProgress || !errors.Contains(st.Error, sentinelErr) || (st.EndTime == time.Time{}) { | ||
t.Fatalf("Unexpected status: %+v", st) | ||
} | ||
// Save end time and verify that finalising again has no effect. | ||
endTime := st.EndTime | ||
s.Finalize(nil) | ||
st = s.Status() | ||
if st.EndTime != endTime || !errors.Contains(st.Error, sentinelErr) { | ||
t.Fatalf("Unexpected status: %+v", st) | ||
} | ||
// Start the same status again. | ||
s.Start() | ||
st = s.Status() | ||
if !st.InProgress || st.Error != nil { | ||
t.Fatalf("Unexpected status: %+v", st) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package sweeper | ||
|
||
import ( | ||
"context" | ||
"github.com/skynetlabs/pinner/skyd" | ||
"github.com/skynetlabs/pinner/sweeper" | ||
"github.com/skynetlabs/pinner/test" | ||
"testing" | ||
"time" | ||
) | ||
|
||
// TestSweeper ensures that Sweeper properly scans skyd and updates the DB. | ||
func TestSweeper(t *testing.T) { | ||
if testing.Short() { | ||
t.SkipNow() | ||
} | ||
t.Parallel() | ||
|
||
ctx := context.Background() | ||
db, err := test.NewDatabase(ctx, t.Name()) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
skydc := skyd.NewSkydClientMock() | ||
serverName := t.Name() | ||
logger := test.NewDiscardLogger() | ||
|
||
// Ensure there are no skylinks pinned by this server, according to the DB. | ||
sls, err := db.SkylinksForServer(ctx, serverName) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
if len(sls) > 0 { | ||
t.Fatalf("Expected no skylinks marked as pinned by this server, got %d", len(sls)) | ||
} | ||
|
||
testSweepPeriod := 100 * time.Millisecond | ||
swpr := sweeper.New(db, skydc, serverName, logger) | ||
swpr.UpdateSchedule(testSweepPeriod) | ||
defer swpr.Close() | ||
|
||
// Wait for the sweep to come and go through. | ||
// Rebuilding the cache will take 100ms. | ||
time.Sleep(300 * time.Millisecond) | ||
|
||
// Ensure the sweep passed and there are skylinks in the DB marked as pinned | ||
// by this server. | ||
sls, err = db.SkylinksForServer(ctx, serverName) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
// Grab the skylinks available in the mock. We expect to see these in the DB. | ||
mockSkylinks := skydc.Skylinks() | ||
if len(sls) != len(mockSkylinks) { | ||
t.Fatalf("Expected %d skylinks, got %d", len(mockSkylinks), len(sls)) | ||
} | ||
// Ensure all skylinks are there. | ||
for _, s := range mockSkylinks { | ||
if !test.Contains(sls, s) { | ||
t.Fatalf("Missing skylink '%s'", s) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters