Skip to content

Commit

Permalink
feat: invoke save on panic (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
plastikfan committed Nov 13, 2024
1 parent adceafc commit eb30766
Show file tree
Hide file tree
Showing 21 changed files with 483 additions and 46 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"ineffassign",
"Innerworld",
"jdef",
"jdir",
"jibberjabber",
"jroot",
"Kontroller",
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ require (
github.com/pkg/errors v0.9.1
github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/snivilised/li18ngo v0.1.9
github.com/snivilised/nefilim v0.1.9
github.com/snivilised/nefilim v0.1.10
github.com/snivilised/pants v0.1.2
golang.org/x/net v0.30.0 // indirect
golang.org/x/sys v0.26.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ github.com/snivilised/nefilim v0.1.8 h1:Srnl6rw7cB/cy3jQT8QfQ0ZNxumQX0Yj/Z+qH3+5
github.com/snivilised/nefilim v0.1.8/go.mod h1:xcQnPeB+zVD+xgw9yzy0QiMTGqjYNEWKeoaZL0TBQeA=
github.com/snivilised/nefilim v0.1.9 h1:KUUc4b8xeShDiiB15MuI4F9P1VlZF0bOwh/1UWsZLOA=
github.com/snivilised/nefilim v0.1.9/go.mod h1:xcQnPeB+zVD+xgw9yzy0QiMTGqjYNEWKeoaZL0TBQeA=
github.com/snivilised/nefilim v0.1.10 h1:j8EGMZSGgFIjcxaVOvYvn7/r66Q5ffXihmq52F55r/E=
github.com/snivilised/nefilim v0.1.10/go.mod h1:xcQnPeB+zVD+xgw9yzy0QiMTGqjYNEWKeoaZL0TBQeA=
github.com/snivilised/pants v0.1.2 h1:6Abj02gV5rFYyKfCsmeEiOi1pLdRyITKUY5oDoRgYuU=
github.com/snivilised/pants v0.1.2/go.mod h1:BOZa24yLxVjjnTCFWQeCzUWL8eK4TLtXtkz3pMdEFQM=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
Expand Down
16 changes: 7 additions & 9 deletions internal/enclave/enclave-defs.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,6 @@ type (
AssignChildren(children []fs.DirEntry)
}

SaveState struct {
Path string
}

// RestoreState defines properties required in order to instigate
// a resume.
RestoreState struct {
Expand All @@ -136,11 +132,6 @@ type (
OnLoad(active *core.ActiveState)
}

// Loader is to be defined by a unit test and should modify the loaded active state
// for the test's own purposes. This allows the unit tests to be isolated from the
// content of the loaded active state.
Loader func(active *core.ActiveState)

// OptionHarvest
OptionHarvest interface {
Options() *pref.Options
Expand All @@ -149,6 +140,13 @@ type (
}
)

type (
// Loader is to be defined by a unit test and should modify the loaded active state
// for the test's own purposes. This allows the unit tests to be isolated from the
// content of the loaded active state.
Loader func(active *core.ActiveState)
)

func (fn Loader) OnLoad(active *core.ActiveState) {
fn(active)
}
167 changes: 167 additions & 0 deletions internal/feat/resume/save_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package resume_test

import (
"context"

"github.com/fortytw2/leaktest"
. "github.com/onsi/ginkgo/v2" //nolint:revive // ok
. "github.com/onsi/gomega" //nolint:revive // ok
"github.com/snivilised/li18ngo"
nef "github.com/snivilised/nefilim"
"github.com/snivilised/nefilim/test/luna"
tv "github.com/snivilised/traverse"
"github.com/snivilised/traverse/core"
"github.com/snivilised/traverse/enums"
"github.com/snivilised/traverse/internal/enclave"
lab "github.com/snivilised/traverse/internal/laboratory"
"github.com/snivilised/traverse/internal/services"
"github.com/snivilised/traverse/locale"
"github.com/snivilised/traverse/pref"
"github.com/snivilised/traverse/test/hydra"
"github.com/snivilised/traverse/tfs"
)

type arrangementSave struct {
name, jdir string
rS tv.TraversalFS
}

func (s *arrangementSave) arrange() *saveAsserter {
const home = "home/prodigy"

calc := s.rS.Calc()
mocks := &nef.ResolveMocks{
HomeFunc: func() (string, error) {
return calc.Join(s.jdir, "marshal", home), nil
},
}

full, _ := mocks.HomeFunc()
file, err := s.rS.Ensure(nef.PathAs{
Name: full,
Default: s.name,
Perm: lab.Perms.Dir,
})
directory, _ := calc.Split(file)

Expect(err).To(Succeed())
Expect(luna.AsDirectory(directory)).To(luna.ExistInFS(s.rS))

return &saveAsserter{}
}

type saveAsserter struct {
expectedErr error
}

func (a *saveAsserter) assert(result core.TraverseResult, actual, expected error) {
Expect(actual).To(MatchError(expected))
Expect(result).NotTo(BeNil())
}

var _ = Describe("Save", Ordered, func() {
var (
from, jdir string
fS *luna.MemFS
rS tv.TraversalFS
)

BeforeAll(func() {
Expect(li18ngo.Use(
func(o *li18ngo.UseOptions) {
o.From.Sources = li18ngo.TranslationFiles{
locale.SourceID: li18ngo.TranslationSource{Name: "traverse"},
}
},
)).To(Succeed())
from = lab.GetJSONPath()
jdir = lab.GetJSONDir()
})

BeforeEach(func() {
services.Reset()
fS = hydra.Nuxx(verbose, lab.Static.RetroWave)
rS = tfs.New()
})

When("given: panic", func() {
Context("prime", func() {
It("🧪 should: save", func(specCtx SpecContext) {
defer leaktest.Check(GinkgoT())()

ctx, cancel := context.WithCancel(specCtx)
defer cancel()

arranged := (&arrangementSave{
name: "prime.walk.out.something.json",
jdir: jdir,
rS: rS,
}).arrange()

result, err := tv.Walk().Configure().Extent(tv.Prime(
&pref.Using{
Subscription: enums.SubscribeDirectories,
Head: pref.Head{
Handler: lab.PanicAt(lab.Static.TeenageColor),
GetForest: func(_ string) *core.Forest {
return &core.Forest{
T: fS,
R: rS,
}
},
},
Tree: lab.Static.RetroWave,
},
tv.WithOnBegin(lab.Begin("🛡️")),
tv.WithOnEnd(lab.End("🏁")),
)).Navigate(ctx)

arranged.assert(result, err, locale.ErrCorePanicOccurred)
})
})

Context("resume", func() {
It("🧪 should: save", func(specCtx SpecContext) {
defer leaktest.Check(GinkgoT())()

ctx, cancel := context.WithCancel(specCtx)
defer cancel()

arranged := (&arrangementSave{
name: "resume.walk.out.something.json",
jdir: jdir,
rS: rS,
}).arrange()

result, err := tv.Walk().Configure(enclave.Loader(func(active *core.ActiveState) {
active.Tree = lab.Static.RetroWave
active.TraverseDescription = core.FsDescription{
IsRelative: true,
}
active.CurrentPath = lab.Static.NorthernCouncil
active.Subscription = enums.SubscribeUniversal
})).Extent(tv.Resume(
&pref.Relic{
Head: pref.Head{
Handler: lab.PanicAt(lab.Static.ElectricYouth),
GetForest: func(_ string) *core.Forest {
return &core.Forest{
T: fS,
R: rS,
}
},
},
From: from,
Strategy: enums.ResumeStrategyFastward,
},
tv.WithOnBegin(lab.Begin("🛡️")),
tv.WithOnEnd(lab.End("🏁")),
)).Navigate(ctx)

arranged.assert(result, err, locale.ErrCorePanicOccurred)
})
})

// TODO: repeat for concurrent sync.
})
})
8 changes: 5 additions & 3 deletions internal/feat/resume/strategy-fastward.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (f *FastwardFilter) Source() string {

// IsMatch does this node match the filter
func (f *FastwardFilter) IsMatch(node *core.Node) bool {
return node.Extension.Name == f.name && node.Parent.Path == f.parent
return node.Extension.Name == f.name && (node.Parent.Path == f.parent || f.parent == ".")
}

// IsApplicable is this filter applicable to this node's scope
Expand Down Expand Up @@ -76,11 +76,13 @@ type fastwardStrategy struct {
}

func (s *fastwardStrategy) init(load *opts.LoadInfo) (err error) {
// We don't use the Hibernate.Wake/Sleep-At, as those are defined bt the client.
// We don't use the Hibernate.Wake/Sleep-At, as those are defined by the client.
// Instead we just need to create a filter on the fly from the load state...
//
calc := s.forest.T.Calc()
scope := lo.Ternary(load.State.IsDir, enums.ScopeDirectory, enums.ScopeFile)
parent := calc.Dir(load.State.CurrentPath)

s.filter, err = filtering.New(
&core.FilterDef{
Type: enums.FilterTypeCustom,
Expand All @@ -92,7 +94,7 @@ func (s *fastwardStrategy) init(load *opts.LoadInfo) (err error) {
),
scope: scope,
source: load.State.CurrentPath,
parent: calc.Dir(load.State.CurrentPath),
parent: parent,
name: calc.Base(load.State.CurrentPath),
},
},
Expand Down
40 changes: 40 additions & 0 deletions internal/kernel/author.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package kernel

import (
"errors"
"io/fs"

"github.com/snivilised/traverse/internal/persist"
"github.com/snivilised/traverse/pref"
)

type author struct {
o *pref.Options
path string
perm fs.FileMode
}

func (a *author) write(vapour inspection) error {
if a.path == "" {
return errors.New("temporary: write failed, path missing")
}

s := vapour.static()
forest := s.mediator.resources.Forest
active := vapour.active(s.tree, forest,
s.mediator.periscope.Depth(),
s.mediator.metrics,
)

request := &persist.MarshalRequest{
Active: active,
O: a.o,
Path: a.path,
Perm: a.perm,
FS: s.mediator.resources.Forest.R,
}

_, err := persist.Marshal(request)

return err
}
9 changes: 4 additions & 5 deletions internal/kernel/kernel-defs.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,10 @@ type (
inspection interface { // after content has been read
enclave.Inspection
static() *navigationStatic
active(tree string,
forest *core.Forest,
depth int,
metrics core.Metrics) *core.ActiveState
clear()
}

navigationAssets struct {
ns navigationStatic
vapour *navigationVapour
}
)
27 changes: 23 additions & 4 deletions internal/kernel/mediator.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,25 @@ type mediatorInfo struct {
resources *enclave.Resources
}

type (
vexation interface {
vapour() inspection
}

vex struct {
data interface{}
vap inspection
}
)

func (v *vex) Data() interface{} {
return v.data
}

func (v *vex) vapour() inspection {
return v.vap
}

func newMediator(info *mediatorInfo) *mediator {
metrics := info.resources.Supervisor.Many(
enums.MetricNoFilesInvoked,
Expand All @@ -45,7 +64,7 @@ func newMediator(info *mediatorInfo) *mediator {
)

return &mediator{
tree: info.facade.Path(), // TODO: ??? is this right for resume?
tree: info.facade.Path(),
subscription: info.subscription,
impl: info.impl,
guardian: newGuardian(&guardianInfo{
Expand Down Expand Up @@ -102,8 +121,8 @@ func (m *mediator) Conclude(result core.TraverseResult) {
m.resources.Binder.Controls.End.Dispatch()(result)
}

func (m *mediator) Navigate(ctx context.Context) (*enclave.KernelResult, error) {
result, err := m.impl.Top(ctx, &navigationStatic{
func (m *mediator) Navigate(ctx context.Context) (result *enclave.KernelResult, err error) {
result, err = m.impl.Top(ctx, &navigationStatic{
mediator: m,
tree: m.tree,
calc: m.resources.Forest.T.Calc(),
Expand All @@ -122,7 +141,7 @@ func (m *mediator) Read(path string) ([]fs.DirEntry, error) {

func (m *mediator) Resume(ctx context.Context,
active *core.ActiveState,
) (*enclave.KernelResult, error) {
) (result *enclave.KernelResult, err error) {
m.tree = active.Tree
// TODO: there is something missing here...
// we need to do more with the loaded active state
Expand Down
Loading

0 comments on commit eb30766

Please sign in to comment.