aboutsummaryrefslogtreecommitdiffstats
path: root/cache/repo_cache.go
diff options
context:
space:
mode:
Diffstat (limited to 'cache/repo_cache.go')
-rw-r--r--cache/repo_cache.go90
1 files changed, 44 insertions, 46 deletions
diff --git a/cache/repo_cache.go b/cache/repo_cache.go
index 7852ec7d..6e7396ed 100644
--- a/cache/repo_cache.go
+++ b/cache/repo_cache.go
@@ -76,7 +76,7 @@ type RepoCache struct {
// If the returned BuildEvent channel is not nil, the caller is expected to read all events before the cache is considered
// ready to use.
func NewRepoCache(r repository.ClockedRepo) (*RepoCache, chan BuildEvent, error) {
- return NewNamedRepoCache(r, "")
+ return NewNamedRepoCache(r, defaultRepoName)
}
// NewNamedRepoCache create or open a named cache on top of a raw repository.
@@ -101,18 +101,22 @@ func NewNamedRepoCache(r repository.ClockedRepo, name string) (*RepoCache, chan
&BugExcerpt{}: entity.ResolverFunc[*BugExcerpt](c.bugs.ResolveExcerpt),
}
- err := c.lock()
+ // small buffer so that below functions can emit an event without blocking
+ events := make(chan BuildEvent, 10)
+ defer close(events)
+
+ err := c.lock(events)
if err != nil {
- return &RepoCache{}, nil, err
+ return &RepoCache{}, events, err
}
err = c.load()
if err == nil {
- return c, nil, nil
+ return c, events, nil
}
// Cache is either missing, broken or outdated. Rebuilding.
- events := c.buildCache()
+ c.buildCache(events)
return c, events, nil
}
@@ -122,13 +126,11 @@ func NewRepoCacheNoEvents(r repository.ClockedRepo) (*RepoCache, error) {
if err != nil {
return nil, err
}
- if events != nil {
- for event := range events {
- if event.Err != nil {
- for range events {
- }
- return nil, err
+ for event := range events {
+ if event.Err != nil {
+ for range events {
}
+ return nil, err
}
}
return cache, nil
@@ -164,8 +166,8 @@ func (c *RepoCache) load() error {
return errWait.Wait()
}
-func (c *RepoCache) lock() error {
- err := repoIsAvailable(c.repo)
+func (c *RepoCache) lock(events chan BuildEvent) error {
+ err := repoIsAvailable(c.repo, events)
if err != nil {
return err
}
@@ -206,6 +208,8 @@ type BuildEventType int
const (
_ BuildEventType = iota
+ BuildEventCacheIsBuilt
+ BuildEventRemoveLock
BuildEventStarted
BuildEventFinished
)
@@ -214,54 +218,48 @@ const (
type BuildEvent struct {
// Err carry an error if the build process failed. If set, no other field matter.
Err error
- // Typename is the name of the entity of which the event relate to.
+ // Typename is the name of the entity of which the event relate to. Can be empty if not particular entity is involved.
Typename string
// Event is the type of the event.
Event BuildEventType
}
-func (c *RepoCache) buildCache() chan BuildEvent {
- out := make(chan BuildEvent)
+func (c *RepoCache) buildCache(events chan BuildEvent) {
+ events <- BuildEvent{Event: BuildEventCacheIsBuilt}
- go func() {
- defer close(out)
-
- var wg sync.WaitGroup
- for _, subcache := range c.subcaches {
- wg.Add(1)
- go func(subcache cacheMgmt) {
- defer wg.Done()
- out <- BuildEvent{
- Typename: subcache.Typename(),
- Event: BuildEventStarted,
- }
-
- err := subcache.Build()
- if err != nil {
- out <- BuildEvent{
- Typename: subcache.Typename(),
- Err: err,
- }
- return
- }
+ var wg sync.WaitGroup
+ for _, subcache := range c.subcaches {
+ wg.Add(1)
+ go func(subcache cacheMgmt) {
+ defer wg.Done()
+ events <- BuildEvent{
+ Typename: subcache.Typename(),
+ Event: BuildEventStarted,
+ }
- out <- BuildEvent{
+ err := subcache.Build()
+ if err != nil {
+ events <- BuildEvent{
Typename: subcache.Typename(),
- Event: BuildEventFinished,
+ Err: err,
}
- }(subcache)
- }
- wg.Wait()
- }()
+ return
+ }
- return out
+ events <- BuildEvent{
+ Typename: subcache.Typename(),
+ Event: BuildEventFinished,
+ }
+ }(subcache)
+ }
+ wg.Wait()
}
// repoIsAvailable check is the given repository is locked by a Cache.
// Note: this is a smart function that will clean the lock file if the
// corresponding process is not there anymore.
// If no error is returned, the repo is free to edit.
-func repoIsAvailable(repo repository.RepoStorage) error {
+func repoIsAvailable(repo repository.RepoStorage, events chan BuildEvent) error {
// Todo: this leave way for a racey access to the repo between the test
// if the file exist and the actual write. It's probably not a problem in
// practice because using a repository will be done from user interaction
@@ -299,7 +297,7 @@ func repoIsAvailable(repo repository.RepoStorage) error {
// The lock file is just laying there after a crash, clean it
- fmt.Println("A lock file is present but the corresponding process is not, removing it.")
+ events <- BuildEvent{Event: BuildEventRemoveLock}
err = f.Close()
if err != nil {
return err