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