Commit 4635f2c3cd374ddaf963f577535485bcddcf1bf4
1 parent
b3f624151c
Exists in
master
pagination utility
Showing
2 changed files
with
45 additions
and
42 deletions
Show diff stats
pagination.go
File was created | 1 | package webutility | |
2 | |||
3 | import "net/http" | ||
4 | |||
5 | type PaginationParams struct { | ||
6 | URL string | ||
7 | Offset int64 | ||
8 | Limit int64 | ||
9 | SortBy string | ||
10 | Order string | ||
11 | } | ||
12 | |||
13 | func (p *PaginationParams) links() PaginationLinks { | ||
14 | return PaginationLinks{} | ||
15 | } | ||
16 | |||
17 | // PaginationLinks ... | ||
18 | type PaginationLinks struct { | ||
19 | Count int64 | ||
20 | Total int64 | ||
21 | Base string `json:"base"` | ||
22 | Next string `json:"next"` | ||
23 | Prev string `json:"prev"` | ||
24 | Self string `json:"self"` | ||
25 | } | ||
26 | |||
27 | func GetPaginationParameters(req *http.Request) (p PaginationParams) { | ||
28 | p.Offset = StringToInt64(req.FormValue("offset")) | ||
29 | p.Limit = StringToInt64(req.FormValue("limit")) | ||
30 | p.SortBy = req.FormValue("sortBy") | ||
31 | p.Order = req.FormValue("order") | ||
32 | |||
33 | return p | ||
34 | } | ||
35 |
payload.go
1 | package webutility | 1 | package webutility |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "database/sql" | 4 | "database/sql" |
5 | "encoding/json" | 5 | "encoding/json" |
6 | "errors" | 6 | "errors" |
7 | "fmt" | 7 | "fmt" |
8 | "net/http" | 8 | "net/http" |
9 | "strings" | 9 | "strings" |
10 | "sync" | 10 | "sync" |
11 | "time" | 11 | "time" |
12 | ) | 12 | ) |
13 | 13 | ||
14 | var ( | 14 | var ( |
15 | mu = &sync.Mutex{} | 15 | mu = &sync.Mutex{} |
16 | metadata = make(map[string]Payload) | 16 | metadata = make(map[string]Payload) |
17 | 17 | ||
18 | updateQue = make(map[string][]byte) | 18 | updateQue = make(map[string][]byte) |
19 | 19 | ||
20 | metadataDB *sql.DB | 20 | metadataDB *sql.DB |
21 | activeProject string | 21 | activeProject string |
22 | 22 | ||
23 | inited bool | 23 | inited bool |
24 | metaDriver string | 24 | metaDriver string |
25 | ) | 25 | ) |
26 | 26 | ||
27 | // LangMap ... | 27 | // LangMap ... |
28 | type LangMap map[string]map[string]string | 28 | type LangMap map[string]map[string]string |
29 | 29 | ||
30 | // Field ... | 30 | // Field ... |
31 | type Field struct { | 31 | type Field struct { |
32 | Parameter string `json:"param"` | 32 | Parameter string `json:"param"` |
33 | Type string `json:"type"` | 33 | Type string `json:"type"` |
34 | Visible bool `json:"visible"` | 34 | Visible bool `json:"visible"` |
35 | Editable bool `json:"editable"` | 35 | Editable bool `json:"editable"` |
36 | } | 36 | } |
37 | 37 | ||
38 | // CorrelationField ... | 38 | // CorrelationField ... |
39 | type CorrelationField struct { | 39 | type CorrelationField struct { |
40 | Result string `json:"result"` | 40 | Result string `json:"result"` |
41 | Elements []string `json:"elements"` | 41 | Elements []string `json:"elements"` |
42 | Type string `json:"type"` | 42 | Type string `json:"type"` |
43 | } | 43 | } |
44 | 44 | ||
45 | // Translation ... | 45 | // Translation ... |
46 | type Translation struct { | 46 | type Translation struct { |
47 | Language string `json:"language"` | 47 | Language string `json:"language"` |
48 | FieldsLabels map[string]string `json:"fieldsLabels"` | 48 | FieldsLabels map[string]string `json:"fieldsLabels"` |
49 | } | 49 | } |
50 | 50 | ||
51 | // PaginationLinks ... | ||
52 | type PaginationLinks struct { | ||
53 | Base string `json:"base"` | ||
54 | Next string `json:"next"` | ||
55 | Prev string `json:"prev"` | ||
56 | Self string `json:"self"` | ||
57 | } | ||
58 | |||
59 | // PaginationParameters ... | ||
60 | type PaginationParameters struct { | ||
61 | URL string `json:"-"` | ||
62 | Offset int64 `json:"offset"` | ||
63 | Limit int64 `json:"limit"` | ||
64 | SortBy string `json:"sortBy"` | ||
65 | Order string `json:"order"` | ||
66 | } | ||
67 | |||
68 | // GetPaginationParameters ... | ||
69 | // TODO(marko) | ||
70 | func GetPaginationParameters(req *http.Request) (p PaginationParameters) { | ||
71 | return p | ||
72 | } | ||
73 | |||
74 | // TODO(marko) | ||
75 | func (p *PaginationParameters) paginationLinks() (links PaginationLinks) { | ||
76 | return links | ||
77 | } | ||
78 | |||
79 | // Payload ... | 51 | // Payload ... |
80 | type Payload struct { | 52 | type Payload struct { |
81 | Method string `json:"method"` | 53 | Method string `json:"method"` |
82 | Params map[string]string `json:"params"` | 54 | Params map[string]string `json:"params"` |
83 | Lang []Translation `json:"lang"` | 55 | Lang []Translation `json:"lang"` |
84 | Fields []Field `json:"fields"` | 56 | Fields []Field `json:"fields"` |
85 | Correlations []CorrelationField `json:"correlationFields"` | 57 | Correlations []CorrelationField `json:"correlationFields"` |
86 | IDField string `json:"idField"` | 58 | IDField string `json:"idField"` |
87 | 59 | ||
88 | // Pagination | ||
89 | Count int64 `json:"count"` | ||
90 | Total int64 `json:"total"` | ||
91 | Links PaginationLinks `json:"_links"` | 60 | Links PaginationLinks `json:"_links"` |
92 | 61 | ||
93 | // Data holds JSON payload. It can't be used for itteration. | 62 | // Data holds JSON payload. It can't be used for itteration. |
94 | Data interface{} `json:"data"` | 63 | Data interface{} `json:"data"` |
95 | } | 64 | } |
96 | 65 | ||
66 | // NewPayload returs a payload sceleton for entity described with key. | ||
67 | func NewPayload(r *http.Request, key string) Payload { | ||
68 | p := metadata[key] | ||
69 | p.Method = r.Method + " " + r.RequestURI | ||
70 | return p | ||
71 | } | ||
72 | |||
97 | func (p *Payload) addLang(code string, labels map[string]string) { | 73 | func (p *Payload) addLang(code string, labels map[string]string) { |
98 | t := Translation{ | 74 | t := Translation{ |
99 | Language: code, | 75 | Language: code, |
100 | FieldsLabels: labels, | 76 | FieldsLabels: labels, |
101 | } | 77 | } |
102 | p.Lang = append(p.Lang, t) | 78 | p.Lang = append(p.Lang, t) |
103 | } | 79 | } |
104 | 80 | ||
105 | // SetData ... | 81 | // SetData ... |
106 | func (p *Payload) SetData(data interface{}) { | 82 | func (p *Payload) SetData(data interface{}) { |
107 | p.Data = data | 83 | p.Data = data |
108 | } | 84 | } |
109 | 85 | ||
110 | // SetPaginationInfo ... | 86 | // SetPaginationInfo ... |
111 | func (p *Payload) SetPaginationInfo(count, total int64, params PaginationParameters) { | 87 | func (p *Payload) SetPaginationInfo(count, total int64, params PaginationParams) { |
112 | p.Count = count | 88 | p.Links.Count = count |
113 | p.Total = total | 89 | p.Links.Total = total |
114 | p.Links = params.paginationLinks() | 90 | p.Links = params.links() |
115 | } | ||
116 | |||
117 | // NewPayload returs a payload sceleton for entity described with key. | ||
118 | func NewPayload(r *http.Request, key string) Payload { | ||
119 | p := metadata[key] | ||
120 | p.Method = r.Method + " " + r.RequestURI | ||
121 | return p | ||
122 | } | 91 | } |
123 | 92 | ||
124 | // InitPayloadsMetadata loads all payloads' information into 'metadata' variable. | 93 | // InitPayloadsMetadata loads all payloads' information into 'metadata' variable. |
125 | func InitPayloadsMetadata(drv string, db *sql.DB, project string) error { | 94 | func InitPayloadsMetadata(drv string, db *sql.DB, project string) error { |
126 | var err error | 95 | var err error |
127 | if drv != "ora" && drv != "mysql" { | 96 | if drv != "ora" && drv != "mysql" { |
128 | err = errors.New("driver not supported") | 97 | err = errors.New("driver not supported") |
129 | return err | 98 | return err |
130 | } | 99 | } |
131 | 100 | ||
132 | metaDriver = drv | 101 | metaDriver = drv |
133 | metadataDB = db | 102 | metadataDB = db |
134 | activeProject = project | 103 | activeProject = project |
135 | 104 | ||
136 | mu.Lock() | 105 | mu.Lock() |
137 | defer mu.Unlock() | 106 | defer mu.Unlock() |
138 | err = initMetadata(project) | 107 | err = initMetadata(project) |
139 | if err != nil { | 108 | if err != nil { |
140 | return err | 109 | return err |
141 | } | 110 | } |
142 | inited = true | 111 | inited = true |
143 | 112 | ||
144 | return nil | 113 | return nil |
145 | } | 114 | } |
146 | 115 | ||
147 | // EnableHotloading ... | 116 | // EnableHotloading ... |
148 | func EnableHotloading(interval int) { | 117 | func EnableHotloading(interval int) { |
149 | if interval > 0 { | 118 | if interval > 0 { |
150 | go hotload(interval) | 119 | go hotload(interval) |
151 | } | 120 | } |
152 | } | 121 | } |
153 | 122 | ||
154 | // GetMetadataForAllEntities ... | 123 | // GetMetadataForAllEntities ... |
155 | func GetMetadataForAllEntities() map[string]Payload { | 124 | func GetMetadataForAllEntities() map[string]Payload { |
156 | return metadata | 125 | return metadata |
157 | } | 126 | } |
158 | 127 | ||
159 | // GetMetadataForEntity ... | 128 | // GetMetadataForEntity ... |
160 | func GetMetadataForEntity(t string) (Payload, bool) { | 129 | func GetMetadataForEntity(t string) (Payload, bool) { |
161 | p, ok := metadata[t] | 130 | p, ok := metadata[t] |
162 | return p, ok | 131 | return p, ok |
163 | } | 132 | } |
164 | 133 | ||
165 | // QueEntityModelUpdate ... | 134 | // QueEntityModelUpdate ... |
166 | func QueEntityModelUpdate(entityType string, v interface{}) { | 135 | func QueEntityModelUpdate(entityType string, v interface{}) { |
167 | updateQue[entityType], _ = json.Marshal(v) | 136 | updateQue[entityType], _ = json.Marshal(v) |
168 | } | 137 | } |
169 | 138 | ||
170 | // UpdateEntityModels ... | 139 | // UpdateEntityModels ... |
171 | func UpdateEntityModels(command string) (total, upd, add int, err error) { | 140 | func UpdateEntityModels(command string) (total, upd, add int, err error) { |
172 | if command != "force" && command != "missing" { | 141 | if command != "force" && command != "missing" { |
173 | return total, 0, 0, errors.New("webutility: unknown command: " + command) | 142 | return total, 0, 0, errors.New("webutility: unknown command: " + command) |
174 | } | 143 | } |
175 | 144 | ||
176 | if !inited { | 145 | if !inited { |
177 | return 0, 0, 0, errors.New("webutility: metadata not initialized but update was tried") | 146 | return 0, 0, 0, errors.New("webutility: metadata not initialized but update was tried") |
178 | } | 147 | } |
179 | 148 | ||
180 | total = len(updateQue) | 149 | total = len(updateQue) |
181 | 150 | ||
182 | toUpdate := make([]string, 0) | 151 | toUpdate := make([]string, 0) |
183 | toAdd := make([]string, 0) | 152 | toAdd := make([]string, 0) |
184 | 153 | ||
185 | for k := range updateQue { | 154 | for k := range updateQue { |
186 | if _, exists := metadata[k]; exists { | 155 | if _, exists := metadata[k]; exists { |
187 | if command == "force" { | 156 | if command == "force" { |
188 | toUpdate = append(toUpdate, k) | 157 | toUpdate = append(toUpdate, k) |
189 | } | 158 | } |
190 | } else { | 159 | } else { |
191 | toAdd = append(toAdd, k) | 160 | toAdd = append(toAdd, k) |
192 | } | 161 | } |
193 | } | 162 | } |
194 | 163 | ||
195 | var uStmt *sql.Stmt | 164 | var uStmt *sql.Stmt |
196 | if metaDriver == "ora" { | 165 | if metaDriver == "ora" { |
197 | uStmt, err = metadataDB.Prepare("update entities set entity_model = :1 where entity_type = :2") | 166 | uStmt, err = metadataDB.Prepare("update entities set entity_model = :1 where entity_type = :2") |
198 | if err != nil { | 167 | if err != nil { |
199 | return | 168 | return |
200 | } | 169 | } |
201 | } else if metaDriver == "mysql" { | 170 | } else if metaDriver == "mysql" { |
202 | uStmt, err = metadataDB.Prepare("update entities set entity_model = ? where entity_type = ?") | 171 | uStmt, err = metadataDB.Prepare("update entities set entity_model = ? where entity_type = ?") |
203 | if err != nil { | 172 | if err != nil { |
204 | return | 173 | return |
205 | } | 174 | } |
206 | } | 175 | } |
207 | for _, k := range toUpdate { | 176 | for _, k := range toUpdate { |
208 | _, err = uStmt.Exec(string(updateQue[k]), k) | 177 | _, err = uStmt.Exec(string(updateQue[k]), k) |
209 | if err != nil { | 178 | if err != nil { |
210 | return | 179 | return |
211 | } | 180 | } |
212 | upd++ | 181 | upd++ |
213 | } | 182 | } |
214 | 183 | ||
215 | blankPayload, _ := json.Marshal(Payload{}) | 184 | blankPayload, _ := json.Marshal(Payload{}) |
216 | var iStmt *sql.Stmt | 185 | var iStmt *sql.Stmt |
217 | if metaDriver == "ora" { | 186 | if metaDriver == "ora" { |
218 | iStmt, err = metadataDB.Prepare("insert into entities(projekat, metadata, entity_type, entity_model) values(:1, :2, :3, :4)") | 187 | iStmt, err = metadataDB.Prepare("insert into entities(projekat, metadata, entity_type, entity_model) values(:1, :2, :3, :4)") |
219 | if err != nil { | 188 | if err != nil { |
220 | return | 189 | return |
221 | } | 190 | } |
222 | } else if metaDriver == "mysql" { | 191 | } else if metaDriver == "mysql" { |
223 | iStmt, err = metadataDB.Prepare("insert into entities(projekat, metadata, entity_type, entity_model) values(?, ?, ?, ?)") | 192 | iStmt, err = metadataDB.Prepare("insert into entities(projekat, metadata, entity_type, entity_model) values(?, ?, ?, ?)") |
224 | if err != nil { | 193 | if err != nil { |
225 | return | 194 | return |
226 | } | 195 | } |
227 | } | 196 | } |
228 | for _, k := range toAdd { | 197 | for _, k := range toAdd { |
229 | _, err = iStmt.Exec(activeProject, string(blankPayload), k, string(updateQue[k])) | 198 | _, err = iStmt.Exec(activeProject, string(blankPayload), k, string(updateQue[k])) |
230 | if err != nil { | 199 | if err != nil { |
231 | return | 200 | return |
232 | } | 201 | } |
233 | metadata[k] = Payload{} | 202 | metadata[k] = Payload{} |
234 | add++ | 203 | add++ |
235 | } | 204 | } |
236 | 205 | ||
237 | return total, upd, add, nil | 206 | return total, upd, add, nil |
238 | } | 207 | } |
239 | 208 | ||
240 | func initMetadata(project string) error { | 209 | func initMetadata(project string) error { |
241 | rows, err := metadataDB.Query(`select | 210 | rows, err := metadataDB.Query(`select |
242 | entity_type, | 211 | entity_type, |
243 | metadata | 212 | metadata |
244 | from entities | 213 | from entities |
245 | where projekat = ` + fmt.Sprintf("'%s'", project)) | 214 | where projekat = ` + fmt.Sprintf("'%s'", project)) |
246 | if err != nil { | 215 | if err != nil { |
247 | return err | 216 | return err |
248 | } | 217 | } |
249 | defer rows.Close() | 218 | defer rows.Close() |
250 | 219 | ||
251 | if len(metadata) > 0 { | 220 | if len(metadata) > 0 { |
252 | metadata = nil | 221 | metadata = nil |
253 | } | 222 | } |
254 | metadata = make(map[string]Payload) | 223 | metadata = make(map[string]Payload) |
255 | for rows.Next() { | 224 | for rows.Next() { |
256 | var name, load string | 225 | var name, load string |
257 | rows.Scan(&name, &load) | 226 | rows.Scan(&name, &load) |
258 | 227 | ||
259 | p := Payload{} | 228 | p := Payload{} |
260 | err := json.Unmarshal([]byte(load), &p) | 229 | err := json.Unmarshal([]byte(load), &p) |
261 | if err != nil { | 230 | if err != nil { |
262 | fmt.Printf("webutility: couldn't init: '%s' metadata: %s:\n%s\n", name, err.Error(), load) | 231 | fmt.Printf("webutility: couldn't init: '%s' metadata: %s:\n%s\n", name, err.Error(), load) |
263 | } else { | 232 | } else { |
264 | metadata[name] = p | 233 | metadata[name] = p |
265 | } | 234 | } |
266 | } | 235 | } |
267 | 236 | ||
268 | return nil | 237 | return nil |
269 | } | 238 | } |
270 | 239 | ||
271 | // LoadMetadataFromFile expects file in format: | 240 | // LoadMetadataFromFile expects file in format: |
272 | // | 241 | // |
273 | // [ payload A identifier ] | 242 | // [ payload A identifier ] |
274 | // key1 = value1 | 243 | // key1 = value1 |
275 | // key2 = value2 | 244 | // key2 = value2 |
276 | // ... | 245 | // ... |
277 | // [ payload B identifier ] | 246 | // [ payload B identifier ] |
278 | // key1 = value1 | 247 | // key1 = value1 |
279 | // key2 = value2 | 248 | // key2 = value2 |
280 | // ... | 249 | // ... |
281 | // | 250 | // |
282 | // TODO(marko): Currently supports only one hardcoded language... | 251 | // TODO(marko): Currently supports only one hardcoded language... |
283 | func LoadMetadataFromFile(path string) error { | 252 | func LoadMetadataFromFile(path string) error { |
284 | lines, err := ReadFileLines(path) | 253 | lines, err := ReadFileLines(path) |
285 | if err != nil { | 254 | if err != nil { |
286 | return err | 255 | return err |
287 | } | 256 | } |
288 | 257 | ||
289 | metadata = make(map[string]Payload) | 258 | metadata = make(map[string]Payload) |
290 | 259 | ||
291 | var name string | 260 | var name string |
292 | for i, l := range lines { | 261 | for i, l := range lines { |
293 | // skip empty lines | 262 | // skip empty lines |
294 | if l = strings.TrimSpace(l); len(l) == 0 { | 263 | if l = strings.TrimSpace(l); len(l) == 0 { |
295 | continue | 264 | continue |
296 | } | 265 | } |
297 | 266 | ||
298 | if IsWrappedWith(l, "[", "]") { | 267 | if IsWrappedWith(l, "[", "]") { |
299 | name = strings.Trim(l, "[]") | 268 | name = strings.Trim(l, "[]") |
300 | p := Payload{} | 269 | p := Payload{} |
301 | p.addLang("sr", make(map[string]string)) | 270 | p.addLang("sr", make(map[string]string)) |
302 | metadata[name] = p | 271 | metadata[name] = p |
303 | continue | 272 | continue |
304 | } | 273 | } |
305 | 274 | ||
306 | if name == "" { | 275 | if name == "" { |
307 | return fmt.Errorf("webutility: LoadMetadataFromFile: error on line %d: [no header] [%s]", i+1, l) | 276 | return fmt.Errorf("webutility: LoadMetadataFromFile: error on line %d: [no header] [%s]", i+1, l) |
308 | } | 277 | } |
309 | 278 | ||
310 | parts := strings.Split(l, "=") | 279 | parts := strings.Split(l, "=") |
311 | if len(parts) != 2 { | 280 | if len(parts) != 2 { |
312 | return fmt.Errorf("webutility: LoadMetadataFromFile: error on line %d: [invalid format] [%s]", i+1, l) | 281 | return fmt.Errorf("webutility: LoadMetadataFromFile: error on line %d: [invalid format] [%s]", i+1, l) |
313 | } | 282 | } |
314 | 283 | ||
315 | k := strings.TrimSpace(parts[0]) | 284 | k := strings.TrimSpace(parts[0]) |
316 | v := strings.TrimSpace(parts[1]) | 285 | v := strings.TrimSpace(parts[1]) |
317 | if v != "-" { | 286 | if v != "-" { |
318 | metadata[name].Lang[0].FieldsLabels[k] = v | 287 | metadata[name].Lang[0].FieldsLabels[k] = v |
319 | } | 288 | } |
320 | } | 289 | } |
321 | 290 | ||
322 | return nil | 291 | return nil |
323 | } | 292 | } |
324 | 293 | ||
325 | func hotload(n int) { | 294 | func hotload(n int) { |
326 | entityScan := make(map[string]int64) | 295 | entityScan := make(map[string]int64) |
327 | firstCheck := true | 296 | firstCheck := true |
328 | for { | 297 | for { |
329 | time.Sleep(time.Duration(n) * time.Second) | 298 | time.Sleep(time.Duration(n) * time.Second) |
330 | rows, err := metadataDB.Query(`select | 299 | rows, err := metadataDB.Query(`select |
331 | ora_rowscn, | 300 | ora_rowscn, |
332 | entity_type | 301 | entity_type |
333 | from entities where projekat = ` + fmt.Sprintf("'%s'", activeProject)) | 302 | from entities where projekat = ` + fmt.Sprintf("'%s'", activeProject)) |
334 | if err != nil { | 303 | if err != nil { |
335 | fmt.Printf("webutility: hotload failed: %v\n", err) | 304 | fmt.Printf("webutility: hotload failed: %v\n", err) |
336 | time.Sleep(time.Duration(n) * time.Second) | 305 | time.Sleep(time.Duration(n) * time.Second) |
337 | continue | 306 | continue |
338 | } | 307 | } |
339 | 308 | ||
340 | var toRefresh []string | 309 | var toRefresh []string |
341 | for rows.Next() { | 310 | for rows.Next() { |
342 | var scanID int64 | 311 | var scanID int64 |
343 | var entity string | 312 | var entity string |
344 | rows.Scan(&scanID, &entity) | 313 | rows.Scan(&scanID, &entity) |
345 | oldID, ok := entityScan[entity] | 314 | oldID, ok := entityScan[entity] |
346 | if !ok || oldID != scanID { | 315 | if !ok || oldID != scanID { |
347 | entityScan[entity] = scanID | 316 | entityScan[entity] = scanID |
348 | toRefresh = append(toRefresh, entity) | 317 | toRefresh = append(toRefresh, entity) |
349 | } | 318 | } |
350 | } | 319 | } |
351 | rows.Close() | 320 | rows.Close() |
352 | 321 | ||
353 | if rows.Err() != nil { | 322 | if rows.Err() != nil { |
354 | fmt.Printf("webutility: hotload rset error: %v\n", rows.Err()) | 323 | fmt.Printf("webutility: hotload rset error: %v\n", rows.Err()) |
355 | time.Sleep(time.Duration(n) * time.Second) | 324 | time.Sleep(time.Duration(n) * time.Second) |
356 | continue | 325 | continue |
357 | } | 326 | } |
358 | 327 | ||
359 | if len(toRefresh) > 0 && !firstCheck { | 328 | if len(toRefresh) > 0 && !firstCheck { |
360 | mu.Lock() | 329 | mu.Lock() |
361 | refreshMetadata(toRefresh) | 330 | refreshMetadata(toRefresh) |
362 | mu.Unlock() | 331 | mu.Unlock() |
363 | } | 332 | } |
364 | if firstCheck { | 333 | if firstCheck { |
365 | firstCheck = false | 334 | firstCheck = false |
366 | } | 335 | } |
367 | } | 336 | } |
368 | } | 337 | } |
369 | 338 | ||
370 | func refreshMetadata(entities []string) { | 339 | func refreshMetadata(entities []string) { |
371 | for _, e := range entities { | 340 | for _, e := range entities { |
372 | fmt.Printf("refreshing %s\n", e) | 341 | fmt.Printf("refreshing %s\n", e) |
373 | rows, err := metadataDB.Query(`select | 342 | rows, err := metadataDB.Query(`select |
374 | metadata | 343 | metadata |
375 | from entities | 344 | from entities |
376 | where projekat = ` + fmt.Sprintf("'%s'", activeProject) + | 345 | where projekat = ` + fmt.Sprintf("'%s'", activeProject) + |
377 | ` and entity_type = ` + fmt.Sprintf("'%s'", e)) | 346 | ` and entity_type = ` + fmt.Sprintf("'%s'", e)) |
378 | 347 | ||
379 | if err != nil { | 348 | if err != nil { |
380 | fmt.Printf("webutility: refresh: prep: %v\n", err) | 349 | fmt.Printf("webutility: refresh: prep: %v\n", err) |
381 | rows.Close() | 350 | rows.Close() |
382 | continue | 351 | continue |
383 | } | 352 | } |
384 | 353 | ||
385 | for rows.Next() { | 354 | for rows.Next() { |
386 | var load string | 355 | var load string |
387 | rows.Scan(&load) | 356 | rows.Scan(&load) |
388 | p := Payload{} | 357 | p := Payload{} |
389 | err := json.Unmarshal([]byte(load), &p) | 358 | err := json.Unmarshal([]byte(load), &p) |
390 | if err != nil { | 359 | if err != nil { |
391 | fmt.Printf("webutility: couldn't refresh: '%s' metadata: %s\n%s\n", e, err.Error(), load) | 360 | fmt.Printf("webutility: couldn't refresh: '%s' metadata: %s\n%s\n", e, err.Error(), load) |
392 | } else { | 361 | } else { |
393 | metadata[e] = p | 362 | metadata[e] = p |
394 | } | 363 | } |
395 | } | 364 | } |
396 | rows.Close() | 365 | rows.Close() |
397 | } | 366 | } |
398 | } | 367 | } |
399 | 368 | ||
400 | /* | 369 | /* |
401 | func ModifyMetadataForEntity(entityType string, p *Payload) error { | 370 | func ModifyMetadataForEntity(entityType string, p *Payload) error { |
402 | md, err := json.Marshal(*p) | 371 | md, err := json.Marshal(*p) |
403 | if err != nil { | 372 | if err != nil { |
404 | return err | 373 | return err |
405 | } | 374 | } |
406 | 375 | ||
407 | mu.Lock() | 376 | mu.Lock() |
408 | defer mu.Unlock() | 377 | defer mu.Unlock() |
409 | _, err = metadataDB.PrepAndExe(`update entities set | 378 | _, err = metadataDB.PrepAndExe(`update entities set |
410 | metadata = :1 | 379 | metadata = :1 |
411 | where projekat = :2 | 380 | where projekat = :2 |
412 | and entity_type = :3`, | 381 | and entity_type = :3`, |
413 | string(md), | 382 | string(md), |
414 | activeProject, | 383 | activeProject, |
415 | entityType) | 384 | entityType) |
416 | if err != nil { | 385 | if err != nil { |
417 | return err | 386 | return err |
418 | } | 387 | } |
419 | return nil | 388 | return nil |
420 | } | 389 | } |
421 | 390 | ||
422 | func DeleteEntityModel(entityType string) error { | 391 | func DeleteEntityModel(entityType string) error { |
423 | _, err := metadataDB.PrepAndExe("delete from entities where entity_type = :1", entityType) | 392 | _, err := metadataDB.PrepAndExe("delete from entities where entity_type = :1", entityType) |
424 | if err == nil { | 393 | if err == nil { |
425 | mu.Lock() | 394 | mu.Lock() |