mirror of
https://github.com/Theodor-Springmann-Stiftung/kgpz_web.git
synced 2025-10-28 16:45:32 +00:00
214 lines
4.6 KiB
Go
214 lines
4.6 KiB
Go
package app
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
|
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers"
|
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
|
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers"
|
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/gnd"
|
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/xmlprovider"
|
|
)
|
|
|
|
const (
|
|
AGENTS_PATH = "XML/akteure.xml"
|
|
PLACES_PATH = "XML/orte.xml"
|
|
WORKS_PATH = "XML/werke.xml"
|
|
CATEGORIES_PATH = "XML/kategorien.xml"
|
|
|
|
ISSUES_DIR = "XML/stuecke/"
|
|
PIECES_DIR = "XML/beitraege/"
|
|
)
|
|
|
|
type KGPZ struct {
|
|
// LMU is here for file system access
|
|
lmu sync.Mutex
|
|
// GMU is only here to prevent concurrent pulls
|
|
gmu sync.Mutex
|
|
Config *providers.ConfigProvider
|
|
Repo *providers.GitProvider
|
|
GND *gnd.GNDProvider
|
|
Library *xmlprovider.Library
|
|
}
|
|
|
|
func (k *KGPZ) Init() {
|
|
if k.Config.Debug {
|
|
// NOTE: validity checks for poor people, speeding up dev mode:
|
|
if _, err := os.Stat(k.Config.FolderPath); err != nil {
|
|
k.initRepo()
|
|
} else {
|
|
go k.initRepo()
|
|
}
|
|
k.Serialize()
|
|
k.InitGND()
|
|
k.Enrich()
|
|
return
|
|
}
|
|
|
|
k.initRepo()
|
|
k.Serialize()
|
|
k.InitGND()
|
|
k.Enrich()
|
|
}
|
|
|
|
func NewKGPZ(config *providers.ConfigProvider) *KGPZ {
|
|
helpers.AssertNonNil(config, "Config is nil")
|
|
if err := config.Validate(); err != nil {
|
|
helpers.Assert(err, "Error validating config")
|
|
}
|
|
|
|
return &KGPZ{Config: config}
|
|
}
|
|
|
|
func (k *KGPZ) InitGND() {
|
|
if k.GND == nil {
|
|
k.GND = gnd.NewGNDProvider()
|
|
}
|
|
|
|
if err := k.GND.ReadCache(k.Config.GNDPath); err != nil {
|
|
logging.Error(err, "Error reading GND cache")
|
|
}
|
|
}
|
|
|
|
func (k *KGPZ) Enrich() error {
|
|
if k.GND == nil {
|
|
k.InitGND()
|
|
}
|
|
|
|
k.lmu.Lock()
|
|
defer k.lmu.Unlock()
|
|
|
|
if k.Library == nil || k.Library.Agents == nil {
|
|
return nil
|
|
}
|
|
|
|
// INFO: We pass agents by value since we don't want to block the library
|
|
agents := make([]xmlprovider.Agent, len(k.Library.Agents.Items.Agents))
|
|
_ = copy(agents, k.Library.Agents.Items.Agents)
|
|
go func(agents []xmlprovider.Agent) {
|
|
k.GND.FetchPersons(agents)
|
|
k.GND.WriteCache(k.Config.GNDPath)
|
|
}(agents)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (k *KGPZ) Serialize() {
|
|
// TODO: this is error handling from hell
|
|
// There is no need to recreate the whole library if the paths haven't changed
|
|
// We do it to keep the old data if the new data is missing
|
|
|
|
// Preventing pulling and serializing at the same time
|
|
k.gmu.Lock()
|
|
defer k.gmu.Unlock()
|
|
|
|
issues, err := getXMLFiles(filepath.Join(k.Config.FolderPath, ISSUES_DIR))
|
|
helpers.Assert(err, "Error getting issues")
|
|
|
|
pieces, err := getXMLFiles(filepath.Join(k.Config.FolderPath, PIECES_DIR))
|
|
helpers.Assert(err, "Error getting pieces")
|
|
|
|
lib := xmlprovider.NewLibrary(
|
|
[]string{filepath.Join(k.Config.FolderPath, AGENTS_PATH)},
|
|
[]string{filepath.Join(k.Config.FolderPath, PLACES_PATH)},
|
|
[]string{filepath.Join(k.Config.FolderPath, WORKS_PATH)},
|
|
[]string{filepath.Join(k.Config.FolderPath, CATEGORIES_PATH)},
|
|
*issues,
|
|
*pieces)
|
|
|
|
lib.Serialize()
|
|
|
|
// TODO: is it neccessary to lock here, sice gmu lock prevents concurrent locking of the library?
|
|
k.lmu.Lock()
|
|
defer k.lmu.Unlock()
|
|
|
|
if k.Library == nil {
|
|
k.Library = lib
|
|
return
|
|
}
|
|
|
|
if lib.Agents == nil {
|
|
lib.Agents = k.Library.Agents
|
|
}
|
|
|
|
if lib.Places == nil {
|
|
lib.Places = k.Library.Places
|
|
}
|
|
|
|
if lib.Works == nil {
|
|
lib.Works = k.Library.Works
|
|
}
|
|
|
|
if lib.Categories == nil {
|
|
lib.Categories = k.Library.Categories
|
|
}
|
|
|
|
if lib.Issues == nil {
|
|
lib.Issues = k.Library.Issues
|
|
}
|
|
|
|
if lib.Pieces == nil {
|
|
lib.Pieces = k.Library.Pieces
|
|
}
|
|
|
|
k.Library = lib
|
|
}
|
|
|
|
func (k *KGPZ) IsDebug() bool {
|
|
return k.Config.Debug
|
|
}
|
|
|
|
func (k *KGPZ) Pull() {
|
|
go func() {
|
|
logging.Info("Pulling Repository...")
|
|
k.gmu.Lock()
|
|
|
|
if k.Repo == nil {
|
|
k.gmu.Unlock()
|
|
return
|
|
}
|
|
|
|
err, changed := k.Repo.Pull()
|
|
logging.Error(err, "Error pulling GitProvider")
|
|
|
|
// Need to unlock here to prevent deadlock, since Serialize locks the same mutex
|
|
k.gmu.Unlock()
|
|
|
|
if changed {
|
|
logging.ObjDebug(&k.Repo, "Remote changed. Reparsing")
|
|
k.Serialize()
|
|
}
|
|
}()
|
|
}
|
|
|
|
func (k *KGPZ) initRepo() {
|
|
gp, err := providers.NewGitProvider(k.Config.Config.GitURL, k.Config.Config.FolderPath, k.Config.Config.GitBranch)
|
|
if err != nil {
|
|
logging.ObjErr(&gp, err, "Error creating GitProvider")
|
|
return
|
|
}
|
|
|
|
k.gmu.Lock()
|
|
k.Repo = gp
|
|
k.gmu.Unlock()
|
|
k.Pull()
|
|
|
|
logging.ObjDebug(&k.Repo, "GitProvider initialized")
|
|
}
|
|
|
|
func (k *KGPZ) Shutdown() {
|
|
k.Repo.Wait()
|
|
}
|
|
|
|
func getXMLFiles(path string) (*[]string, error) {
|
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
|
return nil, err
|
|
}
|
|
|
|
matches, err := filepath.Glob(filepath.Join(path, "*.xml"))
|
|
|
|
return &matches, err
|
|
}
|