Commit 67337ffa8f7b0c4ef26040aa3f09c492d659afab

Authored by Marko Tikvić
1 parent 2ea67927f5
Exists in master and in 1 other branch v2

payload editing

Showing 1 changed file with 67 additions and 40 deletions   Show diff stats
1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "encoding/json" 4 "encoding/json"
5 "errors" 5 "errors"
6 "fmt" 6 "fmt"
7 "io" 7 "io"
8 "net/http" 8 "net/http"
9 "os" 9 "os"
10 "sync" 10 "sync"
11 "time" 11 "time"
12 12
13 "gopkg.in/rana/ora.v4" 13 "gopkg.in/rana/ora.v4"
14 ) 14 )
15 15
16 var ( 16 var (
17 mu = &sync.Mutex{} 17 mu = &sync.Mutex{}
18 metadata map[string]Payload 18 metadata = make(map[string]Payload)
19 updateQue = make(map[string][]byte)
19 20
20 metadataDB *ora.Ses 21 metadataDB *ora.Ses
21 activeProject string 22 activeProject string
22 23
23 inited bool 24 inited bool
24 ) 25 )
25 26
26 type LangMap map[string]map[string]string 27 type LangMap map[string]map[string]string
27 28
28 type Field struct { 29 type Field struct {
29 Parameter string `json:"param"` 30 Parameter string `json:"param"`
30 Type string `json:"type"` 31 Type string `json:"type"`
31 Visible bool `json:"visible"` 32 Visible bool `json:"visible"`
32 Editable bool `json:"editable"` 33 Editable bool `json:"editable"`
33 } 34 }
34 35
35 type CorrelationField struct { 36 type CorrelationField struct {
36 Result string `json:"result"` 37 Result string `json:"result"`
37 Elements []string `json:"elements"` 38 Elements []string `json:"elements"`
38 Type string `json:"type"` 39 Type string `json:"type"`
39 } 40 }
40 41
41 type Translation struct { 42 type Translation struct {
42 Language string `json:"language"` 43 Language string `json:"language"`
43 FieldsLabels map[string]string `json:"fieldsLabels"` 44 FieldsLabels map[string]string `json:"fieldsLabels"`
44 } 45 }
45 46
46 type Payload struct { 47 type Payload struct {
47 Method string `json:"method"` 48 Method string `json:"method"`
48 Params map[string]string `json:"params"` 49 Params map[string]string `json:"params"`
49 Lang []Translation `json:"lang"` 50 Lang []Translation `json:"lang"`
50 Fields []Field `json:"fields"` 51 Fields []Field `json:"fields"`
51 Correlations []CorrelationField `json:"correlationFields"` 52 Correlations []CorrelationField `json:"correlationFields"`
52 IdField string `json:"idField"` 53 IdField string `json:"idField"`
53 54
54 // Data holds JSON payload. It can't be used for itteration. 55 // Data holds JSON payload. It can't be used for itteration.
55 Data interface{} `json:"data"` 56 Data interface{} `json:"data"`
56 } 57 }
57 58
58 // LoadPayloadsdetaData loads all payloads' information into 'metadata' variable. 59 // LoadPayloadsdetaData loads all payloads' information into 'metadata' variable.
59 func LoadPayloadsMetadata(db *ora.Ses, project string, hotloading bool, hlPeriod int) error { 60 func LoadPayloadsMetadata(db *ora.Ses, project string, hotloading bool, hlPeriod int) error {
60 metadataDB = db 61 metadataDB = db
61 activeProject = project 62 activeProject = project
62 63
63 mu.Lock() 64 mu.Lock()
64 defer mu.Unlock() 65 defer mu.Unlock()
65 err := initMetadata(project) 66 err := initMetadata(project)
66 if err != nil { 67 if err != nil {
67 return err 68 return err
68 } 69 }
69 if hotloading { 70 if hotloading {
70 go hotload(hlPeriod) 71 go hotload(hlPeriod)
71 } 72 }
72 inited = true 73 inited = true
73 74
74 return nil 75 return nil
75 } 76 }
76 77
77 func UpdateMetadataModels(md map[string][]byte) (upd, add int, err error) { 78 func GetMetadataForAllEntities() map[string]Payload {
79 return metadata
80 }
81
82 func GetMetadataForEntity(t string) (Payload, bool) {
83 p, ok := metadata[t]
84 return p, ok
85 }
86
87 func QueEntityModelUpdate(entityType string, v interface{}) {
88 updateQue[entityType], _ = json.Marshal(v)
89 }
90
91 func UpdateEntityModels(forceUpdate bool) (total, upd, add int, err error) {
78 if !inited { 92 if !inited {
79 return 0, 0, errors.New("webutil: metadata not initialized but update was tried.") 93 return 0, 0, 0, errors.New("webutil: metadata not initialized but update was tried.")
80 } 94 }
81 95
96 total = len(updateQue)
97
82 forUpdate := make([]string, 0) 98 forUpdate := make([]string, 0)
83 forCreate := make([]string, 0) 99 forAdd := make([]string, 0)
84 100
85 for k, _ := range md { 101 for k, _ := range updateQue {
86 if _, exists := metadata[k]; exists { 102 if _, exists := metadata[k]; exists {
87 forUpdate = append(forUpdate, k) 103 if forceUpdate {
104 forUpdate = append(forUpdate, k)
105 }
88 } else { 106 } else {
89 forCreate = append(forCreate, k) 107 forAdd = append(forAdd, k)
90 } 108 }
91 } 109 }
92 110
93 for _, k := range forUpdate { 111 for _, k := range forUpdate {
94 fmt.Printf("for update: %s\n", k) 112 fmt.Printf("for update: %s\n", k)
113
95 _, err := metadataDB.PrepAndExe(`update entities set 114 _, err := metadataDB.PrepAndExe(`update entities set
96 entity_model = :1 115 entity_model = :1
97 where entity_type = :2`, 116 where entity_type = :2`,
98 string(md[k]), 117 string(updateQue[k]),
99 k) 118 k)
100 119
101 if err != nil { 120 if err != nil {
102 fmt.Printf("webutility: update metadata: prep and exe: %v\n", err) 121 fmt.Printf("webutility: update metadata: prep and exe: %v\n", err)
103 continue 122 continue
104 } 123 }
105 upd++ 124 upd++
106 } 125 }
107 126
108 for _, k := range forCreate { 127 blankPayload, _ := json.Marshal(Payload{})
128 for _, k := range forAdd {
109 fmt.Printf("for add: %s\n", k) 129 fmt.Printf("for add: %s\n", k)
110 /*
111 _, err := metadataDB.PrepAndExe(`insert into entities
112 (projekat, metadata, entity_type, entity_model)
113 values(:1, :2, :3, :4)`,
114 activeProject, "", k, string(md[k]))
115 130
116 if err != nil { 131 _, err := metadataDB.PrepAndExe(`insert into entities
117 fmt.Printf("webutility: add metadata: prep and exe: %v\n", err) 132 (projekat, metadata, entity_type, entity_model)
118 continue 133 values(:1, :2, :3, :4)`,
119 } 134 activeProject,
120 */ 135 string(blankPayload),
136 k,
137 string(updateQue[k]))
138
139 if err != nil {
140 fmt.Printf("webutility: add metadata: prep and exe: %v\n", err)
141 continue
142 }
143 metadata[k] = Payload{}
121 add++ 144 add++
122 } 145 }
123 146
124 return upd, add, nil 147 return total, upd, add, nil
125 }
126
127 func GetMetadataForAllEntities() map[string]Payload {
128 return metadata
129 }
130
131 func GetMetadataForEntityType(t string) Payload {
132 return metadata[t]
133 } 148 }
134 149
135 func UpdateMetadata(entityType string, p *Payload) error { 150 func ModifyMetadataForEntity(entityType string, p *Payload) error {
136 md, err := json.Marshal(p) 151 md, err := json.Marshal(*p)
137 if err != nil { 152 if err != nil {
138 return err 153 return err
139 } 154 }
140 fmt.Printf("md: %s %s\n", entityType, string(md)) 155
141 mu.Lock() 156 mu.Lock()
142 defer mu.Unlock() 157 defer mu.Unlock()
143 _, err = metadataDB.PrepAndExe(`update entities set 158 _, err = metadataDB.PrepAndExe(`update entities set
144 metadata = :1 159 metadata = :1
145 where projekat = :2 160 where projekat = :2
146 and entity_type = :3`, 161 and entity_type = :3`,
147 string(md), 162 string(md),
148 activeProject, 163 activeProject,
149 entityType) 164 entityType)
150 if err != nil { 165 if err != nil {
151 return err 166 return err
152 } 167 }
153 return nil 168 return nil
154 } 169 }
155 170
156 // DecodeJSON decodes JSON data from r to v. 171 func DeleteEntityModel(entityType string) error {
157 // Returns an error if it fails. 172 _, err := metadataDB.PrepAndExe("delete from entities where entity_type = :1", entityType)
158 func DecodeJSON(r io.Reader, v interface{}) error { 173 if err == nil {
159 return json.NewDecoder(r).Decode(v) 174 mu.Lock()
175 delete(metadata, entityType)
176 mu.Unlock()
177 }
178 return err
160 } 179 }
161 180
162 // NewPayload returs a payload sceleton for entity described with etype. 181 // NewPayload returs a payload sceleton for entity described with etype.
163 func NewPayload(r *http.Request, etype string) Payload { 182 func NewPayload(r *http.Request, etype string) Payload {
164 pload := metadata[etype] 183 pload := metadata[etype]
165 pload.Method = r.Method + " " + r.RequestURI 184 pload.Method = r.Method + " " + r.RequestURI
166 return pload 185 return pload
167 } 186 }
168 187
188 // DecodeJSON decodes JSON data from r to v.
189 // Returns an error if it fails.
190 func DecodeJSON(r io.Reader, v interface{}) error {
191 return json.NewDecoder(r).Decode(v)
192 }
193
169 func initMetadata(project string) error { 194 func initMetadata(project string) error {
170 metadataDB.SetCfg(metadataDB.Cfg().SetClob(ora.S)) 195 metadataDB.SetCfg(metadataDB.Cfg().SetClob(ora.S))
171 stmt, err := metadataDB.Prep(`select 196 stmt, err := metadataDB.Prep(`select
172 entity_type, 197 entity_type,
173 metadata 198 metadata
174 from entities 199 from entities
175 where projekat = `+fmt.Sprintf("'%s'", project), 200 where projekat = `+fmt.Sprintf("'%s'", project),
176 ora.S, 201 ora.S,
177 ora.S) 202 ora.S)
178 203
179 defer stmt.Close() 204 defer stmt.Close()
180 if err != nil { 205 if err != nil {
181 return err 206 return err
182 } 207 }
183 208
184 rset, err := stmt.Qry() 209 rset, err := stmt.Qry()
185 if err != nil { 210 if err != nil {
186 return err 211 return err
187 } 212 }
188 213
189 count := 0 214 count := 0
190 success := 0 215 success := 0
216 if len(metadata) > 0 {
217 metadata = nil
218 }
191 metadata = make(map[string]Payload) 219 metadata = make(map[string]Payload)
192 for rset.Next() { 220 for rset.Next() {
193 name := rset.Row[0].(string) 221 name := rset.Row[0].(string)
194 load := []byte(rset.Row[1].(string)) 222 load := []byte(rset.Row[1].(string))
195 223
196 p := Payload{} 224 p := Payload{}
197 err := json.Unmarshal(load, &p) 225 err := json.Unmarshal(load, &p)
198 if err != nil { 226 if err != nil {
199 fmt.Printf("couldn't init: '%s' metadata\n", name) 227 fmt.Printf("couldn't init: '%s' metadata\n", name)
200 } else { 228 } else {
201 success++ 229 success++
202 metadata[name] = p 230 metadata[name] = p
203 } 231 }
204 count++ 232 count++
205 } 233 }
206 fmt.Printf("webutility: successfully loaded %d/%d (%.1f%%) entities\n", 234 fmt.Printf("webutility: successfully loaded %d/%d (%.1f%%) entities\n",
207 success, count, float32(success)/float32(count)*100.0) 235 success, count, float32(success)/float32(count)*100.0)
208 236
209 return nil 237 return nil
210 } 238 }
211 239
212 func hotload(n int) { 240 func hotload(n int) {
213 entityScan := make(map[string]int64) 241 entityScan := make(map[string]int64)
214 firstCheck := true 242 firstCheck := true
215 for { 243 for {
216 time.Sleep(time.Duration(n) * time.Second) 244 time.Sleep(time.Duration(n) * time.Second)
217 stmt, err := metadataDB.Prep(`select 245 stmt, err := metadataDB.Prep(`select
218 ora_rowscn, 246 ora_rowscn,
219 entity_type 247 entity_type
220 from entities where projekat = `+fmt.Sprintf("'%s'", activeProject), 248 from entities where projekat = `+fmt.Sprintf("'%s'", activeProject),
221 ora.I64, 249 ora.I64,
222 ora.S) 250 ora.S)
223 if err != nil { 251 if err != nil {
224 fmt.Fprintf(os.Stderr, "hotload failed: %v\n", err) 252 fmt.Fprintf(os.Stderr, "hotload failed: %v\n", err)
225 time.Sleep(time.Duration(n) * time.Second) 253 time.Sleep(time.Duration(n) * time.Second)
226 continue 254 continue
227 } 255 }
228 256
229 rset, err := stmt.Qry() 257 rset, err := stmt.Qry()
230 if err != nil { 258 if err != nil {
231 fmt.Fprintf(os.Stderr, "hotload failed: %v\n", err) 259 fmt.Fprintf(os.Stderr, "hotload failed: %v\n", err)
232 time.Sleep(time.Duration(n) * time.Second) 260 time.Sleep(time.Duration(n) * time.Second)
233 continue 261 continue
234 } 262 }
235 263
236 var toRefresh []string 264 var toRefresh []string
237 for rset.Next() { 265 for rset.Next() {
238 scanID := rset.Row[0].(int64) 266 scanID := rset.Row[0].(int64)
239 entity := rset.Row[1].(string) 267 entity := rset.Row[1].(string)
240 oldID, ok := entityScan[entity] 268 oldID, ok := entityScan[entity]
241 if !ok || oldID != scanID { 269 if !ok || oldID != scanID {
242 entityScan[entity] = scanID 270 entityScan[entity] = scanID
243 toRefresh = append(toRefresh, entity) 271 toRefresh = append(toRefresh, entity)
244 } 272 }
245 } 273 }
246 stmt.Close() 274 stmt.Close()
247 275
248 if rset.Err() != nil { 276 if rset.Err() != nil {
249 fmt.Fprintf(os.Stderr, "hotload rset error: %v\n", rset.Err()) 277 fmt.Fprintf(os.Stderr, "hotload rset error: %v\n", rset.Err())
250 time.Sleep(time.Duration(n) * time.Second) 278 time.Sleep(time.Duration(n) * time.Second)
251 continue 279 continue
252 } 280 }
253 281
254 if len(toRefresh) > 0 && !firstCheck { 282 if len(toRefresh) > 0 && !firstCheck {
255 mu.Lock() 283 mu.Lock()
256 refreshMetadata(toRefresh) 284 refreshMetadata(toRefresh)
257 mu.Unlock() 285 mu.Unlock()
258 } 286 }
259 if firstCheck { 287 if firstCheck {
260 firstCheck = false 288 firstCheck = false
261 } 289 }
262 } 290 }
263 } 291 }
264 292
265 func refreshMetadata(entities []string) { 293 func refreshMetadata(entities []string) {
266 for _, e := range entities { 294 for _, e := range entities {
267 //fmt.Printf("refreshing %s\n", e) 295 fmt.Printf("refreshing %s\n", e)
268 stmt, err := metadataDB.Prep(`select 296 stmt, err := metadataDB.Prep(`select
269 metadata 297 metadata
270 from entities 298 from entities
271 where projekat = `+fmt.Sprintf("'%s'", activeProject)+ 299 where projekat = `+fmt.Sprintf("'%s'", activeProject)+
272 ` and entity_type = `+fmt.Sprintf("'%s'", e), 300 ` and entity_type = `+fmt.Sprintf("'%s'", e),
273 ora.S) 301 ora.S)
274 302
275 if err != nil { 303 if err != nil {
276 fmt.Printf("webutility: refresh: prep: %v\n", err) 304 fmt.Printf("webutility: refresh: prep: %v\n", err)
277 stmt.Close() 305 stmt.Close()
278 continue 306 continue
279 } 307 }
280 308
281 rset, err := stmt.Qry() 309 rset, err := stmt.Qry()
282 if err != nil { 310 if err != nil {
283 fmt.Printf("webutility: refresh: query: %v\n", err) 311 fmt.Printf("webutility: refresh: query: %v\n", err)
284 stmt.Close() 312 stmt.Close()
285 continue 313 continue
286 } 314 }
287 315
288 for rset.Next() { 316 for rset.Next() {