2023-03-28 20:43:45 +02:00
|
|
|
package app
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-04-11 12:05:51 +02:00
|
|
|
"sort"
|
2023-03-29 11:27:47 +02:00
|
|
|
"sync"
|
2023-03-28 20:43:45 +02:00
|
|
|
|
|
|
|
"forge.cadoles.com/arcad/edge/pkg/app"
|
|
|
|
"forge.cadoles.com/arcad/edge/pkg/bundle"
|
|
|
|
appModule "forge.cadoles.com/arcad/edge/pkg/module/app"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"gitlab.com/wpetit/goweb/logger"
|
|
|
|
)
|
|
|
|
|
2023-04-05 23:21:43 +02:00
|
|
|
type ResolveAppURLFunc func(context.Context, *app.Manifest, string) (string, error)
|
2023-03-28 20:43:45 +02:00
|
|
|
|
|
|
|
type AppRepository struct {
|
2023-04-05 23:21:43 +02:00
|
|
|
resolveAppURL ResolveAppURLFunc
|
|
|
|
bundles []string
|
|
|
|
mutex sync.RWMutex
|
2023-03-28 20:43:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get implements app.Repository
|
|
|
|
func (r *AppRepository) Get(ctx context.Context, id app.ID) (*app.Manifest, error) {
|
2023-03-29 11:27:47 +02:00
|
|
|
r.mutex.RLock()
|
|
|
|
defer r.mutex.RUnlock()
|
|
|
|
|
2023-03-28 20:43:45 +02:00
|
|
|
manifest, err := r.findManifest(ctx, id)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return manifest, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetURL implements app.Repository
|
2023-04-05 23:21:43 +02:00
|
|
|
func (r *AppRepository) GetURL(ctx context.Context, id app.ID, from string) (string, error) {
|
2023-03-29 11:27:47 +02:00
|
|
|
r.mutex.RLock()
|
|
|
|
defer r.mutex.RUnlock()
|
|
|
|
|
2023-03-28 20:43:45 +02:00
|
|
|
manifest, err := r.findManifest(ctx, id)
|
|
|
|
if err != nil {
|
|
|
|
return "", errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
2023-04-05 23:21:43 +02:00
|
|
|
url, err := r.resolveAppURL(ctx, manifest, from)
|
2023-03-28 20:43:45 +02:00
|
|
|
if err != nil {
|
|
|
|
return "", errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return url, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// List implements app.Repository
|
|
|
|
func (r *AppRepository) List(ctx context.Context) ([]*app.Manifest, error) {
|
2023-03-29 11:27:47 +02:00
|
|
|
r.mutex.RLock()
|
|
|
|
defer r.mutex.RUnlock()
|
|
|
|
|
2023-03-28 20:43:45 +02:00
|
|
|
manifests := make([]*app.Manifest, 0)
|
|
|
|
|
|
|
|
for _, path := range r.bundles {
|
|
|
|
bundleCtx := logger.With(ctx, logger.F("path", path))
|
|
|
|
|
|
|
|
bundle, err := bundle.FromPath(path)
|
|
|
|
if err != nil {
|
2023-10-13 12:30:52 +02:00
|
|
|
err = errors.WithStack(err)
|
2023-10-19 22:09:18 +02:00
|
|
|
logger.Error(bundleCtx, "could not load bundle", logger.CapturedE(err))
|
2023-03-28 20:43:45 +02:00
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
manifest, err := app.LoadManifest(bundle)
|
|
|
|
if err != nil {
|
2023-10-13 12:30:52 +02:00
|
|
|
err = errors.WithStack(err)
|
2023-10-19 22:09:18 +02:00
|
|
|
logger.Error(bundleCtx, "could not load manifest", logger.CapturedE(err))
|
2023-03-28 20:43:45 +02:00
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
manifests = append(manifests, manifest)
|
|
|
|
}
|
|
|
|
|
2023-04-11 12:05:51 +02:00
|
|
|
sort.Sort(ByID(manifests))
|
|
|
|
|
2023-03-28 20:43:45 +02:00
|
|
|
return manifests, nil
|
|
|
|
}
|
|
|
|
|
2023-04-05 23:21:43 +02:00
|
|
|
func (r *AppRepository) Update(resolveAppURL ResolveAppURLFunc, bundles []string) {
|
2023-03-29 11:27:47 +02:00
|
|
|
r.mutex.Lock()
|
|
|
|
defer r.mutex.Unlock()
|
|
|
|
|
2023-04-05 23:21:43 +02:00
|
|
|
r.resolveAppURL = resolveAppURL
|
2023-03-29 11:27:47 +02:00
|
|
|
r.bundles = bundles
|
|
|
|
}
|
|
|
|
|
2023-03-28 20:43:45 +02:00
|
|
|
func (r *AppRepository) findManifest(ctx context.Context, id app.ID) (*app.Manifest, error) {
|
|
|
|
for _, path := range r.bundles {
|
|
|
|
bundleCtx := logger.With(ctx, logger.F("path", path))
|
|
|
|
|
|
|
|
bundle, err := bundle.FromPath(path)
|
|
|
|
if err != nil {
|
2023-10-13 12:30:52 +02:00
|
|
|
err = errors.WithStack(err)
|
2023-10-19 22:09:18 +02:00
|
|
|
logger.Error(bundleCtx, "could not load bundle", logger.CapturedE(err))
|
2023-03-28 20:43:45 +02:00
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
manifest, err := app.LoadManifest(bundle)
|
|
|
|
if err != nil {
|
2023-10-13 12:30:52 +02:00
|
|
|
err = errors.WithStack(err)
|
2023-10-19 22:09:18 +02:00
|
|
|
logger.Error(bundleCtx, "could not load manifest", logger.CapturedE(err))
|
2023-03-28 20:43:45 +02:00
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if manifest.ID != id {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
return manifest, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, errors.WithStack(appModule.ErrNotFound)
|
|
|
|
}
|
|
|
|
|
2023-03-29 11:27:47 +02:00
|
|
|
func NewAppRepository() *AppRepository {
|
|
|
|
return &AppRepository{
|
2023-04-05 23:21:43 +02:00
|
|
|
resolveAppURL: func(ctx context.Context, m *app.Manifest, from string) (string, error) {
|
2023-03-29 11:27:47 +02:00
|
|
|
return "", errors.New("unavailable")
|
|
|
|
},
|
|
|
|
bundles: []string{},
|
|
|
|
}
|
2023-03-28 20:43:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var _ appModule.Repository = &AppRepository{}
|
2023-04-11 12:05:51 +02:00
|
|
|
|
|
|
|
type ByID []*app.Manifest
|
|
|
|
|
|
|
|
func (a ByID) Len() int { return len(a) }
|
|
|
|
func (a ByID) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
|
|
func (a ByID) Less(i, j int) bool { return a[i].ID > a[j].ID }
|