-
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.
* cdb dependency install * caching * selected, resolved dep * cdb * better cdb caching * debug logs * fix typos / cleanup * working dependency tree * cdb * recurse * partially working resolution * resolve * cdb * select_dep * wip * route props * navbar component * stats update * cdb * install --------- Co-authored-by: BuckarooBanzay <[email protected]>
- Loading branch information
1 parent
f8356fc
commit 4986a3e
Showing
32 changed files
with
812 additions
and
253 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package cdb | ||
|
||
import ( | ||
"fmt" | ||
"time" | ||
|
||
cache "github.com/Code-Hex/go-generics-cache" | ||
) | ||
|
||
type CachedCDBClient struct { | ||
ttl time.Duration | ||
client *CDBClient | ||
search_cache *cache.Cache[string, []*Package] | ||
dependency_cache *cache.Cache[string, PackageDependency] | ||
detail_cache *cache.Cache[string, *PackageDetails] | ||
} | ||
|
||
func NewCachedClient(client *CDBClient, ttl time.Duration) *CachedCDBClient { | ||
return &CachedCDBClient{ | ||
ttl: ttl, | ||
client: client, | ||
search_cache: cache.New[string, []*Package](), | ||
dependency_cache: cache.New[string, PackageDependency](), | ||
detail_cache: cache.New[string, *PackageDetails](), | ||
} | ||
} | ||
|
||
func (c *CachedCDBClient) SearchPackages(q *PackageQuery) ([]*Package, error) { | ||
key := q.Params().Encode() | ||
res, ok := c.search_cache.Get(key) | ||
|
||
var err error | ||
if !ok { | ||
res, err = c.client.SearchPackages(q) | ||
if err != nil { | ||
return nil, err | ||
} | ||
c.search_cache.Set(key, res, cache.WithExpiration(c.ttl)) | ||
} | ||
return res, nil | ||
} | ||
|
||
func (c *CachedCDBClient) GetDependencies(author, name string) (PackageDependency, error) { | ||
key := fmt.Sprintf("%s/%s", author, name) | ||
res, ok := c.dependency_cache.Get(key) | ||
|
||
var err error | ||
if !ok { | ||
res, err = c.client.GetDependencies(author, name) | ||
if err != nil { | ||
return nil, err | ||
} | ||
c.dependency_cache.Set(key, res, cache.WithExpiration(c.ttl)) | ||
} | ||
return res, nil | ||
} | ||
|
||
func (c *CachedCDBClient) GetDetails(author, name string) (*PackageDetails, error) { | ||
key := fmt.Sprintf("%s/%s", author, name) | ||
res, ok := c.detail_cache.Get(key) | ||
|
||
var err error | ||
if !ok { | ||
res, err = c.client.GetDetails(author, name) | ||
if err != nil { | ||
return nil, err | ||
} | ||
c.detail_cache.Set(key, res, cache.WithExpiration(c.ttl)) | ||
} | ||
return res, nil | ||
} |
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,128 @@ | ||
package cdb | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
type ResolvedDependency struct { | ||
Name string `json:"name"` | ||
Choices []string `json:"choices"` | ||
Selected string `json:"selected"` | ||
Installed bool `json:"installed"` | ||
} | ||
|
||
func ResolveDependencies(cc *CachedCDBClient, required_pkg string, selected_pkgs, installed_pkgs []string) ([]*ResolvedDependency, error) { | ||
rd := []*ResolvedDependency{} | ||
|
||
// already processed dependencies | ||
processed_deps := map[string]bool{} | ||
|
||
// convert to lookup maps | ||
installed_pkg_map := map[string]bool{} | ||
for _, pkg := range installed_pkgs { | ||
installed_pkg_map[pkg] = true | ||
} | ||
|
||
selected_pkg_map := map[string]bool{} | ||
for _, pkg := range selected_pkgs { | ||
selected_pkg_map[pkg] = true | ||
} | ||
|
||
mod_list, err := cc.SearchPackages(&PackageQuery{Type: []PackageType{PackageTypeMod}}) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to query mods: %v", err) | ||
} | ||
|
||
mod_map := map[string]*Package{} | ||
for _, pkg := range mod_list { | ||
mod_map[GetPackagename(pkg.Author, pkg.Name)] = pkg | ||
} | ||
|
||
resolved_dep_infos := map[string][]*DependencyInfo{} | ||
|
||
// recursive resolver | ||
var resolve func(string) error | ||
resolve = func(pkgname string) error { | ||
if processed_deps[pkgname] { | ||
return nil | ||
} | ||
processed_deps[pkgname] = true | ||
|
||
dep := resolved_dep_infos[pkgname] | ||
author, name := GetAuthorName(pkgname) | ||
|
||
if dep == nil { | ||
// fetch dep infos | ||
deps, err := cc.GetDependencies(author, name) | ||
if err != nil { | ||
return fmt.Errorf("failed to resolve deps for mod '%s': %v", pkgname, err) | ||
} | ||
|
||
for n, dep := range deps { | ||
resolved_dep_infos[n] = dep | ||
} | ||
dep = resolved_dep_infos[pkgname] | ||
} | ||
|
||
if dep == nil { | ||
// should not happen but check anyway | ||
return fmt.Errorf("dep unresolved: '%s'", pkgname) | ||
} | ||
|
||
for _, di := range dep { | ||
if di.IsOptional || processed_deps[di.Name] { | ||
// optional or already processed | ||
continue | ||
} | ||
|
||
processed_deps[di.Name] = true | ||
|
||
d := &ResolvedDependency{ | ||
Name: di.Name, | ||
Choices: []string{}, | ||
} | ||
|
||
if installed_pkg_map[di.Name] { | ||
// already installed | ||
d.Installed = true | ||
rd = append(rd, d) | ||
continue | ||
} | ||
|
||
var selected_pkgname string | ||
for _, dep_pkgname := range di.Packages { | ||
if mod_map[dep_pkgname] == nil { | ||
// not of "mod"-type | ||
continue | ||
} | ||
|
||
d.Choices = append(d.Choices, dep_pkgname) | ||
_, name := GetAuthorName(dep_pkgname) | ||
if (selected_pkgname == "" && name == di.Name) || selected_pkg_map[dep_pkgname] { | ||
// exact match found or manually selected | ||
selected_pkgname = dep_pkgname | ||
} | ||
} | ||
|
||
if selected_pkgname != "" { | ||
d.Selected = selected_pkgname | ||
// resolve selected sub-package | ||
err = resolve(selected_pkgname) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
rd = append(rd, d) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
err = resolve(required_pkg) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return rd, nil | ||
} |
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,32 @@ | ||
package cdb_test | ||
|
||
import ( | ||
"mtui/api/cdb" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestResolveDependencies(t *testing.T) { | ||
c := cdb.New() | ||
cc := cdb.NewCachedClient(c, time.Hour*1) | ||
|
||
installed_pkgs := []string{"default"} | ||
selected_pkgs := []string{} | ||
|
||
rd, err := cdb.ResolveDependencies(cc, "mt-mods/technic_plus", selected_pkgs, installed_pkgs) | ||
assert.NoError(t, err) | ||
assert.NotNil(t, rd) | ||
|
||
for _, di := range rd { | ||
switch di.Name { | ||
case "basic_materials": | ||
assert.True(t, len(di.Choices) >= 1) | ||
case "default": | ||
assert.True(t, di.Installed) | ||
} | ||
} | ||
|
||
assert.Equal(t, 3, len(rd)) | ||
} |
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,15 @@ | ||
package cdb | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
func GetAuthorName(pkgname string) (string, string) { | ||
parts := strings.Split(pkgname, "/") | ||
return parts[0], parts[1] | ||
} | ||
|
||
func GetPackagename(author, name string) string { | ||
return fmt.Sprintf("%s/%s", author, name) | ||
} |
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 |
---|---|---|
|
@@ -16,7 +16,7 @@ func logCleanup(a *app.App) { | |
} | ||
} | ||
|
||
// re-schedule every minute | ||
// re-schedule | ||
time.Sleep(time.Second * 10) | ||
} | ||
} |
Oops, something went wrong.