Skip to content

Commit

Permalink
Disregard and remove legacy open rounds recovered by Service
Browse files Browse the repository at this point in the history
  • Loading branch information
poszu committed Sep 13, 2023
1 parent 00a5521 commit f59d0e4
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 12 deletions.
12 changes: 12 additions & 0 deletions service/round.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"strconv"
Expand Down Expand Up @@ -102,6 +103,17 @@ func NewRound(datadir string, epoch uint, opts ...newRoundOptionFunc) (*round, e
opt(r)
}

err := r.loadState()
switch {
case errors.Is(err, fs.ErrNotExist):
// No state file, this is a new round.
if err := r.saveState(); err != nil {
return nil, err
}
case err != nil:
return nil, err

Check warning on line 114 in service/round.go

View check run for this annotation

Codecov / codecov/patch

service/round.go#L111-L114

Added lines #L111 - L114 were not covered by tests
}

return r, nil
}

Expand Down
4 changes: 0 additions & 4 deletions service/round_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ func TestRound_StateRecovery(t *testing.T) {
recovered, err := NewRound(tmpdir, 0)
require.NoError(t, err)
t.Cleanup(func() { assert.NoError(t, recovered.Teardown(context.Background(), false)) })
require.NoError(t, recovered.loadState())

// Verify
require.False(t, recovered.IsFinished())
Expand All @@ -132,7 +131,6 @@ func TestRound_StateRecovery(t *testing.T) {
recovered, err := NewRound(tmpdir, 0)
require.NoError(t, err)
t.Cleanup(func() { assert.NoError(t, recovered.Teardown(context.Background(), false)) })
require.NoError(t, recovered.loadState())

// Verify
require.False(t, recovered.IsFinished())
Expand Down Expand Up @@ -167,7 +165,6 @@ func TestRound_ExecutionRecovery(t *testing.T) {
{
round, err := NewRound(tmpdir, 1)
req.NoError(err)
req.NoError(round.loadState())

ctx, stop := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer stop()
Expand All @@ -179,7 +176,6 @@ func TestRound_ExecutionRecovery(t *testing.T) {
{
round, err := NewRound(tmpdir, 1)
req.NoError(err)
req.NoError(round.loadState())

req.NoError(round.RecoverExecution(context.Background(), time.Now().Add(400*time.Millisecond), 0))
validateProof(t, round.execution)
Expand Down
11 changes: 4 additions & 7 deletions service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,11 +244,6 @@ func (s *Service) recover(ctx context.Context) (executing *round, err error) {
return nil, fmt.Errorf("failed to create round: %w", err)
}

err = r.loadState()
if err != nil {
return nil, fmt.Errorf("invalid round state: %w", err)
}

logger.Info("recovered round", zap.Uint("epoch", r.epoch))

switch {
Expand All @@ -261,9 +256,11 @@ func (s *Service) recover(ctx context.Context) (executing *round, err error) {
)
s.onNewProof(ctx, r.epoch, r.execution)
r.Teardown(ctx, true)

case r.executionStarted.IsZero():
// An open round from a previous poet version
logger.Info("round is open, removing it", zap.Uint("epoch", r.epoch))
r.Teardown(ctx, true)
default:
// Round is in executing state.
logger.Info(
"round is executing",
zap.Time("started", r.executionStarted),
Expand Down
56 changes: 55 additions & 1 deletion service/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ import (
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"go.uber.org/zap/zaptest"
"golang.org/x/sync/errgroup"

"github.com/spacemeshos/poet/hash"
"github.com/spacemeshos/poet/logging"
"github.com/spacemeshos/poet/server"
"github.com/spacemeshos/poet/service"
"github.com/spacemeshos/poet/service/mocks"
Expand Down Expand Up @@ -222,7 +225,58 @@ func TestRecoverFinishedRound(t *testing.T) {
req.Eventually(func() bool {
_, err := os.Lstat(filepath.Join(datadir, "rounds", "9876"))
return errors.Is(err, os.ErrNotExist)
}, time.Second, 10*time.Millisecond)
}, time.Second*5, 10*time.Millisecond)

cancel()
req.NoError(eg.Wait())
}

func TestRemoveRecoveredOpenRound(t *testing.T) {
req := require.New(t)
ctx := logging.NewContext(context.Background(), zaptest.NewLogger(t))
datadir := t.TempDir()

// manually create a round and execute it
round, err := service.NewRound(
filepath.Join(datadir, "rounds"),
1,
service.WithMembershipRoot([]byte{1, 2, 3, 4}),
)
req.NoError(err)
t.Cleanup(func() { assert.NoError(t, round.Teardown(ctx, false)) })
ctxE, cancel := context.WithTimeout(ctx, time.Millisecond*10)
defer cancel()
err = round.Execute(ctxE, time.Now().Add(time.Hour), 0, 0)
req.ErrorIs(err, context.DeadlineExceeded)

// manually create an open round
openRound, err := service.NewRound(
filepath.Join(datadir, "rounds"),
2,
service.WithMembershipRoot([]byte{1, 2, 3, 4}),
)
req.NoError(err)
t.Cleanup(func() { assert.NoError(t, openRound.Teardown(ctx, true)) })

transport := transport.NewInMemory()
s, err := service.New(
ctx,
time.Now(),
datadir,
transport,
&server.RoundConfig{EpochDuration: time.Hour},
)
req.NoError(err)

ctx, cancel = context.WithCancel(ctx)
defer cancel()
var eg errgroup.Group
eg.Go(func() error { return s.Run(ctx) })

req.Eventually(func() bool {
_, err := os.Lstat(filepath.Join(datadir, "rounds", "2"))
return errors.Is(err, os.ErrNotExist)
}, time.Second*5, 10*time.Millisecond)

cancel()
req.NoError(eg.Wait())
Expand Down

0 comments on commit f59d0e4

Please sign in to comment.