Skip to content

Commit af101c3

Browse files
committed
Persistent database states now seem to work. Probably still need more testing.
1 parent 055fbad commit af101c3

File tree

5 files changed

+76
-38
lines changed

5 files changed

+76
-38
lines changed

databases/databases.go

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,20 @@ type Database interface {
5959
Load(state DatabaseSaveState) error
6060
}
6161

62-
// data representing a saved database state -- useful for service restarts
62+
// represents a saved database state (for service restarts)
6363
type DatabaseSaveState struct {
6464
// database name
6565
Name string
6666
// serialized database in bytes
6767
Data []byte
6868
}
6969

70+
// represents a collection of saved database states
71+
type DatabaseSaveStates struct {
72+
// mapping of orcid/database keys to database save states
73+
Data map[string]DatabaseSaveState
74+
}
75+
7076
// parameters that define a search for files
7177
type SearchParameters struct {
7278
// ElasticSearch query string
@@ -149,27 +155,30 @@ func NewDatabase(orcid, dbName string) (Database, error) {
149155

150156
// saves the internal states of all resident databases, returning a map to
151157
// their save states
152-
func Save() (map[string]DatabaseSaveState, error) {
153-
states := make(map[string]DatabaseSaveState)
158+
func Save() (DatabaseSaveStates, error) {
159+
states := DatabaseSaveStates{
160+
Data: make(map[string]DatabaseSaveState),
161+
}
154162
for key, db := range allDatabases_ {
155163
saveState, err := db.Save()
156164
if err != nil {
157-
return nil, err
165+
return states, err
158166
}
159-
states[key] = saveState
167+
states.Data[key] = saveState
160168
}
161169
return states, nil
162170
}
163171

164172
// loads a previously saved map of save states for all databases, restoring
165173
// their previous states
166-
func Load(states map[string]DatabaseSaveState) error {
167-
for key, state := range states {
168-
orcidIndex := strings.LastIndex(key, "db: ") + 3
169-
if orcidIndex == 2 {
174+
func Load(states DatabaseSaveStates) error {
175+
for key, state := range states.Data {
176+
start := strings.Index(key, "orcid: ") + 8
177+
end := strings.Index(key, "db: ") - 1
178+
if start == 7 || end == -2 {
170179
return fmt.Errorf("Couldn't load saved state for database '%s'", state.Name)
171180
}
172-
orcid := key[orcidIndex:]
181+
orcid := key[start:end]
173182
db, err := NewDatabase(orcid, state.Name)
174183
if err != nil {
175184
return err

databases/jdp/database.go

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"slices"
3636
"strconv"
3737
"strings"
38+
"time"
3839
"unicode"
3940

4041
"github.com/google/uuid"
@@ -59,8 +60,14 @@ type Database struct {
5960
// SSO token used for interim JDP access
6061
SsoToken string
6162
// mapping from staging UUIDs to JDP restoration request ID
62-
// FIXME: not persistent between service restarts!!
63-
StagingIds map[uuid.UUID]int
63+
StagingRequests map[uuid.UUID]StagingRequest
64+
}
65+
66+
type StagingRequest struct {
67+
// JDP staging request ID
68+
Id int
69+
// time of staging request (for purging)
70+
Time time.Time
6471
}
6572

6673
func NewDatabase(orcid string) (databases.Database, error) {
@@ -86,11 +93,11 @@ func NewDatabase(orcid string) (databases.Database, error) {
8693
}
8794

8895
return &Database{
89-
Id: "jdp",
90-
Orcid: orcid,
91-
Secret: secret,
92-
SsoToken: os.Getenv("DTS_JDP_SSO_TOKEN"),
93-
StagingIds: make(map[uuid.UUID]int),
96+
Id: "jdp",
97+
Orcid: orcid,
98+
Secret: secret,
99+
SsoToken: os.Getenv("DTS_JDP_SSO_TOKEN"),
100+
StagingRequests: make(map[uuid.UUID]StagingRequest),
94101
}, nil
95102
}
96103

@@ -279,7 +286,10 @@ func (db *Database) StageFiles(fileIds []string) (uuid.UUID, error) {
279286
slog.Debug(fmt.Sprintf("Requested %d archived files from JDP (request ID: %d)",
280287
len(fileIds), jdpResp.RequestId))
281288
xferId = uuid.New()
282-
db.StagingIds[xferId] = jdpResp.RequestId
289+
db.StagingRequests[xferId] = StagingRequest{
290+
Id: jdpResp.RequestId,
291+
Time: time.Now(),
292+
}
283293
return xferId, err
284294
case 404:
285295
return xferId, databases.ResourceNotFoundError{
@@ -292,9 +302,9 @@ func (db *Database) StageFiles(fileIds []string) (uuid.UUID, error) {
292302
}
293303

294304
func (db *Database) StagingStatus(id uuid.UUID) (databases.StagingStatus, error) {
295-
// FIXME: db.StagingIds is not persistent between service restarts!!
296-
if restoreId, found := db.StagingIds[id]; found {
297-
resource := fmt.Sprintf("request_archived_files/requests/%d", restoreId)
305+
db.pruneStagingRequests()
306+
if request, found := db.StagingRequests[id]; found {
307+
resource := fmt.Sprintf("request_archived_files/requests/%d", request.Id)
298308
resp, err := db.get(resource, url.Values{})
299309
if err != nil {
300310
return databases.StagingStatusUnknown, err
@@ -336,19 +346,19 @@ func (db *Database) LocalUser(orcid string) (string, error) {
336346
func (db Database) Save() (databases.DatabaseSaveState, error) {
337347
var buffer bytes.Buffer
338348
enc := gob.NewEncoder(&buffer)
339-
err := enc.Encode(db.StagingIds)
349+
err := enc.Encode(db.StagingRequests)
340350
if err != nil {
341351
return databases.DatabaseSaveState{}, err
342352
}
343353
return databases.DatabaseSaveState{
344-
Name: "NMDC",
354+
Name: "jdp",
345355
Data: buffer.Bytes(),
346356
}, nil
347357
}
348358

349359
func (db *Database) Load(state databases.DatabaseSaveState) error {
350360
enc := gob.NewDecoder(bytes.NewReader(state.Data))
351-
return enc.Decode(&db.StagingIds)
361+
return enc.Decode(&db.StagingRequests)
352362
}
353363

354364
//--------------------
@@ -853,3 +863,13 @@ func (db Database) addSpecificSearchParameters(params map[string]json.RawMessage
853863
}
854864
return nil
855865
}
866+
867+
func (db *Database) pruneStagingRequests() {
868+
deleteAfter := time.Duration(config.Service.DeleteAfter) * time.Second
869+
for uuid, request := range db.StagingRequests {
870+
requestAge := time.Since(request.Time)
871+
if requestAge > deleteAfter {
872+
delete(db.StagingRequests, uuid)
873+
}
874+
}
875+
}

databases/kbase/database.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,15 @@ func (db *Database) LocalUser(orcid string) (string, error) {
7777
// auth server proxy
7878
return auth.KBaseLocalUsernameForOrcid(orcid)
7979
}
80+
81+
func (db Database) Save() (databases.DatabaseSaveState, error) {
82+
// so far, this database has no internal state
83+
return databases.DatabaseSaveState{
84+
Name: "kbase",
85+
}, nil
86+
}
87+
88+
func (db *Database) Load(state databases.DatabaseSaveState) error {
89+
// no internal state -> nothing to do
90+
return nil
91+
}

databases/nmdc/database.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ func (db Database) LocalUser(orcid string) (string, error) {
240240
func (db Database) Save() (databases.DatabaseSaveState, error) {
241241
// so far, this database has no internal state
242242
return databases.DatabaseSaveState{
243-
Name: "NMDC",
243+
Name: "nmdc",
244244
}, nil
245245
}
246246

tasks/tasks.go

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -257,18 +257,17 @@ func createOrLoadTasks(dataFile string) map[uuid.UUID]transferTask {
257257
defer file.Close()
258258
enc := gob.NewDecoder(file)
259259
var tasks map[uuid.UUID]transferTask
260-
err = enc.Decode(&tasks)
261-
if err == nil {
262-
var databaseStates map[string]DatabaseSaveState
260+
var databaseStates databases.DatabaseSaveStates
261+
if err = enc.Decode(&tasks); err == nil {
263262
err = enc.Decode(&databaseStates)
264-
if err == nil {
265-
err = databases.Load(databaseStates)
266-
}
267263
}
268264
if err != nil { // file not readable
269265
slog.Error(fmt.Sprintf("Reading task file %s: %s", dataFile, err.Error()))
270266
return make(map[uuid.UUID]transferTask)
271267
}
268+
if err = databases.Load(databaseStates); err != nil {
269+
slog.Error(fmt.Sprintf("Restoring database states: %s", err.Error()))
270+
}
272271
slog.Debug(fmt.Sprintf("Restored %d tasks from %s", len(tasks), dataFile))
273272
return tasks
274273
}
@@ -282,10 +281,11 @@ func saveTasks(tasks map[uuid.UUID]transferTask, dataFile string) error {
282281
return fmt.Errorf("Opening task file %s: %s", dataFile, err.Error())
283282
}
284283
enc := gob.NewEncoder(file)
285-
err = enc.Encode(tasks)
286-
if err == nil {
287-
databaseStates := databases.Save()
288-
err = enc.Encode(databaseStates)
284+
if err = enc.Encode(tasks); err == nil {
285+
var databaseStates databases.DatabaseSaveStates
286+
if databaseStates, err = databases.Save(); err == nil {
287+
err = enc.Encode(databaseStates)
288+
}
289289
}
290290
if err != nil {
291291
file.Close()
@@ -375,7 +375,6 @@ func processTasks() {
375375
case <-pollChan: // time to move things along
376376
for taskId, task := range tasks {
377377
if !task.Completed() {
378-
slog.Debug(fmt.Sprintf("Task %s is incomplete, proceeding...", taskId.String()))
379378
oldStatus := task.Status
380379
err := task.Update()
381380
if err != nil {
@@ -404,8 +403,6 @@ func processTasks() {
404403
slog.Info(fmt.Sprintf("Task %s: failed", task.Id.String()))
405404
}
406405
}
407-
} else {
408-
slog.Debug(fmt.Sprintf("Task %s is complete.", taskId.String()))
409406
}
410407

411408
// if the task completed a long enough time go, delete its entry

0 commit comments

Comments
 (0)