package repository import ( "encoding/json" "errors" "fmt" "io/fs" "os" "path/filepath" "strings" "github.com/spf13/viper" "git.kplus.net.ua/yevhen/resource-scraper/types/resource" ) // srrdbNormalizedPath turns a search path into a file name. The two characters // that carry structure in a path are swapped for look-alikes, so the name still // reads as the query it came from and can be reversed character by character. func srrdbNormalizedPath(uri string) string { return strings.NewReplacer(":", ":", "/", "∕").Replace(uri) + ".json" } // srrdbDumpPath is the guard file of a search path inside srrdb.dump_dir. func srrdbDumpPath(uri string) string { return filepath.Join(viper.GetString("srrdb.dump_dir"), srrdbNormalizedPath(uri)) } // srrdbExists reports whether a dump file is present. Any stat failure other than // "not found" is returned as an error: treating it as absent would let the run // overwrite a dump it has no right to read. func srrdbExists(path string) (bool, error) { _, err := os.Stat(path) switch { case err == nil: return true, nil case errors.Is(err, fs.ErrNotExist): return false, nil default: return false, fmt.Errorf("stat srrdb dump %q: %w", path, err) } } // srrdbWriteDump stores the merged answer as indented JSON. It runs only after // the database is updated, therefore the presence of the file means the whole // run completed. // // The directory is never created here: it holds the cursor of the walk and is made // once by hand, like the database file. func srrdbWriteDump(path string, all *resource.SrrdbSearchResponse) error { data, err := json.MarshalIndent(all, "", " ") if err != nil { return fmt.Errorf("encode srrdb dump %q: %w", path, err) } if err := os.WriteFile(path, data, 0o644); err != nil { return fmt.Errorf("write srrdb dump %q: %w", path, err) } return nil }