This repository has been archived by the owner on Apr 2, 2024. It is now read-only.
generated from mrz1836/go-template
-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
model_save.go
128 lines (111 loc) · 3.36 KB
/
model_save.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package bux
import (
"context"
"fmt"
"time"
"github.com/mrz1836/go-datastore"
"github.com/pkg/errors"
)
// Save will save the model(s) into the Datastore
func Save(ctx context.Context, model ModelInterface) (err error) {
// Check for a client
c := model.Client()
if c == nil {
return ErrMissingClient
}
// Check for a datastore
ds := c.Datastore()
if ds == nil {
return ErrDatastoreRequired
}
// Create new Datastore transaction
// @siggi: we need this to be in a callback context for Mongo
// NOTE: a DB error is not being returned from here
return ds.NewTx(ctx, func(tx *datastore.Transaction) (err error) {
// Fire the before hooks (parent model)
if model.IsNew() {
if err = model.BeforeCreating(ctx); err != nil {
return
}
} else {
if err = model.BeforeUpdating(ctx); err != nil {
return
}
}
// Set the record's timestamps
model.SetRecordTime(model.IsNew())
// Start the list of models to Save
modelsToSave := append(make([]ModelInterface, 0), model)
// Add any child models (fire before hooks)
if children := model.ChildModels(); len(children) > 0 {
for _, child := range children {
if child.IsNew() {
if err = child.BeforeCreating(ctx); err != nil {
return
}
} else {
if err = child.BeforeUpdating(ctx); err != nil {
return
}
}
// Set the record's timestamps
child.SetRecordTime(child.IsNew())
}
// Add to list for saving
modelsToSave = append(modelsToSave, children...)
}
// Logs for saving models
model.DebugLog(fmt.Sprintf("saving %d models...", len(modelsToSave)))
// Save all models (or fail!)
for index := range modelsToSave {
modelsToSave[index].DebugLog("starting to save model: " + modelsToSave[index].Name() + " id: " + modelsToSave[index].GetID())
if err = modelsToSave[index].Client().Datastore().SaveModel(
ctx, modelsToSave[index], tx, modelsToSave[index].IsNew(), false,
); err != nil {
return
}
}
// Commit all the model(s) if needed
if tx.CanCommit() {
model.DebugLog("committing db transaction...")
if err = tx.Commit(); err != nil {
return
}
}
// Fire after hooks (only on commit success)
var afterErr error
for index := range modelsToSave {
if modelsToSave[index].IsNew() {
modelsToSave[index].NotNew() // NOTE: calling it before this method... after created assumes it's been saved already
afterErr = modelsToSave[index].AfterCreated(ctx)
} else {
afterErr = modelsToSave[index].AfterUpdated(ctx)
}
if afterErr != nil {
if err == nil { // First error - set the error
err = afterErr
} else { // Got more than one error, wrap it!
err = errors.Wrap(err, afterErr.Error())
}
}
// modelToSave.NotNew() // NOTE: moved to above from here
}
return
})
}
// saveToCache will save the model to the cache using the given key(s)
//
// ttl of 0 will cache forever
func saveToCache(ctx context.Context, keys []string, model ModelInterface, ttl time.Duration) error { //nolint:nolintlint,unparam // this does not matter
// NOTE: this check is in place in-case a model does not load its parent Client()
if model.Client() != nil {
for _, key := range keys {
if err := model.Client().Cachestore().SetModel(ctx, key, model, ttl); err != nil {
return err
}
}
} else {
model.DebugLog("ignoring saveToCache: client or cachestore is missing")
}
return nil
}