Blame view

json_utility.go 7.26 KB
ea858b8a7   Marko Tikvić   refactoring
1
  package webutility
64041a2ea   Marko Tikvić   first commit
2
3
  
  import (
8dbe745c3   Marko Tikvić   merged tables uti...
4
5
  	"encoding/json"
  	"errors"
66478e04f   Marko Tikvić   payload now retur...
6
  	"fmt"
8dbe745c3   Marko Tikvić   merged tables uti...
7
  	"io"
d2ddf82ef   Marko Tikvić   started on new rbac
8
  	"net/http"
2ea67927f   Marko Tikvić   added support for...
9
  	"os"
17a4d0447   Marko Tikvić   mutex lock for pa...
10
  	"sync"
2ea67927f   Marko Tikvić   added support for...
11
  	"time"
1d0f61553   Marko Tikvić   can't fetch clob
12

0e41f4d80   Marko Tikvić   refactored due to...
13
  	"git.to-net.rs/marko.tikvic/gologger"
1d0f61553   Marko Tikvić   can't fetch clob
14
  	"gopkg.in/rana/ora.v4"
64041a2ea   Marko Tikvić   first commit
15
  )
2ea67927f   Marko Tikvić   added support for...
16
  var (
67337ffa8   Marko Tikvić   payload editing
17
18
19
  	mu        = &sync.Mutex{}
  	metadata  = make(map[string]Payload)
  	updateQue = make(map[string][]byte)
2ea67927f   Marko Tikvić   added support for...
20
21
22
23
24
25
  
  	metadataDB    *ora.Ses
  	activeProject string
  
  	inited bool
  )
8dbe745c3   Marko Tikvić   merged tables uti...
26

0e41f4d80   Marko Tikvić   refactored due to...
27
28
29
30
  var logger *gologger.Logger
  
  func init() {
  	var err error
04651a369   Marko Tikvić   new log name
31
  	logger, err = gologger.New("metadata", gologger.MaxLogSize100KB)
0e41f4d80   Marko Tikvić   refactored due to...
32
33
34
35
36
  	if err != nil {
  		fmt.Printf("webutility: %s
  ", err.Error())
  	}
  }
64041a2ea   Marko Tikvić   first commit
37
38
39
  type LangMap map[string]map[string]string
  
  type Field struct {
d2ddf82ef   Marko Tikvić   started on new rbac
40
41
42
43
  	Parameter string `json:"param"`
  	Type      string `json:"type"`
  	Visible   bool   `json:"visible"`
  	Editable  bool   `json:"editable"`
64041a2ea   Marko Tikvić   first commit
44
  }
8dbe745c3   Marko Tikvić   merged tables uti...
45
46
47
48
49
50
51
  type CorrelationField struct {
  	Result   string   `json:"result"`
  	Elements []string `json:"elements"`
  	Type     string   `json:"type"`
  }
  
  type Translation struct {
ecec68b18   Marko Tikvić   updated todo list
52
  	Language     string            `json:"language"`
8dbe745c3   Marko Tikvić   merged tables uti...
53
  	FieldsLabels map[string]string `json:"fieldsLabels"`
64041a2ea   Marko Tikvić   first commit
54
  }
4a51e54d7   Marko Tikvić   simplified
55
  type Payload struct {
d2ddf82ef   Marko Tikvić   started on new rbac
56
57
58
59
  	Method       string             `json:"method"`
  	Params       map[string]string  `json:"params"`
  	Lang         []Translation      `json:"lang"`
  	Fields       []Field            `json:"fields"`
4a51e54d7   Marko Tikvić   simplified
60
61
  	Correlations []CorrelationField `json:"correlationFields"`
  	IdField      string             `json:"idField"`
e1fbb41f9   Marko Tikvić   added comments
62

66478e04f   Marko Tikvić   payload now retur...
63
  	// Data holds JSON payload. It can't be used for itteration.
d2ddf82ef   Marko Tikvić   started on new rbac
64
  	Data interface{} `json:"data"`
4a51e54d7   Marko Tikvić   simplified
65
  }
2ea67927f   Marko Tikvić   added support for...
66
  // LoadPayloadsdetaData loads all payloads' information into 'metadata' variable.
61efd58cd   Marko Tikvić   Put hotload enabl...
67
  func LoadPayloadsMetadata(db *ora.Ses, project string) error {
2ea67927f   Marko Tikvić   added support for...
68
69
  	metadataDB = db
  	activeProject = project
62a69beda   Marko Tikvić   Init/Reload Table...
70

2ea67927f   Marko Tikvić   added support for...
71
72
73
  	mu.Lock()
  	defer mu.Unlock()
  	err := initMetadata(project)
d66628295   Marko Tikvić   cleaned up
74
75
76
  	if err != nil {
  		return err
  	}
2ea67927f   Marko Tikvić   added support for...
77
78
79
80
  	inited = true
  
  	return nil
  }
61efd58cd   Marko Tikvić   Put hotload enabl...
81
82
83
84
85
  func EnableHotloading(interval int) {
  	if interval > 0 {
  		go hotload(interval)
  	}
  }
67337ffa8   Marko Tikvić   payload editing
86
87
88
89
90
91
92
93
94
95
96
97
  func GetMetadataForAllEntities() map[string]Payload {
  	return metadata
  }
  
  func GetMetadataForEntity(t string) (Payload, bool) {
  	p, ok := metadata[t]
  	return p, ok
  }
  
  func QueEntityModelUpdate(entityType string, v interface{}) {
  	updateQue[entityType], _ = json.Marshal(v)
  }
4b3627bba   Marko Tikvić   added role ID to ...
98
99
100
101
  func UpdateEntityModels(command string) (total, upd, add int, err error) {
  	if command != "force" && command != "missing" {
  		return total, 0, 0, errors.New("uknown command: " + command)
  	}
2ea67927f   Marko Tikvić   added support for...
102
  	if !inited {
67337ffa8   Marko Tikvić   payload editing
103
  		return 0, 0, 0, errors.New("webutil: metadata not initialized but update was tried.")
2ea67927f   Marko Tikvić   added support for...
104
  	}
67337ffa8   Marko Tikvić   payload editing
105
  	total = len(updateQue)
2ea67927f   Marko Tikvić   added support for...
106
  	forUpdate := make([]string, 0)
67337ffa8   Marko Tikvić   payload editing
107
  	forAdd := make([]string, 0)
2ea67927f   Marko Tikvić   added support for...
108

67337ffa8   Marko Tikvić   payload editing
109
  	for k, _ := range updateQue {
2ea67927f   Marko Tikvić   added support for...
110
  		if _, exists := metadata[k]; exists {
4b3627bba   Marko Tikvić   added role ID to ...
111
  			if command == "force" {
67337ffa8   Marko Tikvić   payload editing
112
113
  				forUpdate = append(forUpdate, k)
  			}
2ea67927f   Marko Tikvić   added support for...
114
  		} else {
67337ffa8   Marko Tikvić   payload editing
115
  			forAdd = append(forAdd, k)
2ea67927f   Marko Tikvić   added support for...
116
117
118
119
  		}
  	}
  
  	for _, k := range forUpdate {
2ea67927f   Marko Tikvić   added support for...
120
  		_, err := metadataDB.PrepAndExe(`update entities set
67337ffa8   Marko Tikvić   payload editing
121
122
123
  			entity_model = :1
  			where entity_type = :2`,
  			string(updateQue[k]),
2ea67927f   Marko Tikvić   added support for...
124
125
126
  			k)
  
  		if err != nil {
0e41f4d80   Marko Tikvić   refactored due to...
127
128
  			logger.Log("webutility: update metadata: prep and exe: %v
  ", err)
2ea67927f   Marko Tikvić   added support for...
129
130
131
  			continue
  		}
  		upd++
0e41f4d80   Marko Tikvić   refactored due to...
132
133
  		logger.Log("webutility: updated %s payload model
  ", k)
2ea67927f   Marko Tikvić   added support for...
134
  	}
67337ffa8   Marko Tikvić   payload editing
135
136
  	blankPayload, _ := json.Marshal(Payload{})
  	for _, k := range forAdd {
67337ffa8   Marko Tikvić   payload editing
137
138
139
140
141
142
143
144
145
  		_, err := metadataDB.PrepAndExe(`insert into entities
  			(projekat, metadata, entity_type, entity_model)
  			values(:1, :2, :3, :4)`,
  			activeProject,
  			string(blankPayload),
  			k,
  			string(updateQue[k]))
  
  		if err != nil {
0e41f4d80   Marko Tikvić   refactored due to...
146
147
  			logger.Log("webutility: add metadata: prep and exe: %v
  ", err)
67337ffa8   Marko Tikvić   payload editing
148
149
150
  			continue
  		}
  		metadata[k] = Payload{}
2ea67927f   Marko Tikvić   added support for...
151
  		add++
0e41f4d80   Marko Tikvić   refactored due to...
152
153
  		logger.Log("webutility: added %s to the payload models
  ", k)
4b3627bba   Marko Tikvić   added role ID to ...
154

2ea67927f   Marko Tikvić   added support for...
155
  	}
67337ffa8   Marko Tikvić   payload editing
156
  	return total, upd, add, nil
2ea67927f   Marko Tikvić   added support for...
157
  }
d66628295   Marko Tikvić   cleaned up
158

67337ffa8   Marko Tikvić   payload editing
159
160
  func ModifyMetadataForEntity(entityType string, p *Payload) error {
  	md, err := json.Marshal(*p)
2ea67927f   Marko Tikvić   added support for...
161
162
163
  	if err != nil {
  		return err
  	}
67337ffa8   Marko Tikvić   payload editing
164

d66628295   Marko Tikvić   cleaned up
165
166
  	mu.Lock()
  	defer mu.Unlock()
2ea67927f   Marko Tikvić   added support for...
167
168
169
170
171
172
173
174
175
  	_, err = metadataDB.PrepAndExe(`update entities set
  		metadata = :1
  		where projekat = :2
  		and entity_type = :3`,
  		string(md),
  		activeProject,
  		entityType)
  	if err != nil {
  		return err
d66628295   Marko Tikvić   cleaned up
176
177
178
  	}
  	return nil
  }
67337ffa8   Marko Tikvić   payload editing
179
180
181
182
183
184
185
186
  func DeleteEntityModel(entityType string) error {
  	_, err := metadataDB.PrepAndExe("delete from entities where entity_type = :1", entityType)
  	if err == nil {
  		mu.Lock()
  		delete(metadata, entityType)
  		mu.Unlock()
  	}
  	return err
d66628295   Marko Tikvić   cleaned up
187
  }
2ea67927f   Marko Tikvić   added support for...
188
189
190
  // NewPayload returs a payload sceleton for entity described with etype.
  func NewPayload(r *http.Request, etype string) Payload {
  	pload := metadata[etype]
2d79a4120   Marko Tikvić   Responses contain...
191
  	pload.Method = r.Method + " " + r.RequestURI
8dbe745c3   Marko Tikvić   merged tables uti...
192
193
  	return pload
  }
64041a2ea   Marko Tikvić   first commit
194

67337ffa8   Marko Tikvić   payload editing
195
196
197
198
199
  // DecodeJSON decodes JSON data from r to v.
  // Returns an error if it fails.
  func DecodeJSON(r io.Reader, v interface{}) error {
  	return json.NewDecoder(r).Decode(v)
  }
2ea67927f   Marko Tikvić   added support for...
200
201
202
203
204
205
206
207
208
209
210
211
212
  func initMetadata(project string) error {
  	metadataDB.SetCfg(metadataDB.Cfg().SetClob(ora.S))
  	stmt, err := metadataDB.Prep(`select
  		entity_type,
  		metadata
  		from entities
  		where projekat = `+fmt.Sprintf("'%s'", project),
  		ora.S,
  		ora.S)
  
  	defer stmt.Close()
  	if err != nil {
  		return err
64041a2ea   Marko Tikvić   first commit
213
  	}
8dbe745c3   Marko Tikvić   merged tables uti...
214

2ea67927f   Marko Tikvić   added support for...
215
216
217
218
  	rset, err := stmt.Qry()
  	if err != nil {
  		return err
  	}
8dbe745c3   Marko Tikvić   merged tables uti...
219

2ea67927f   Marko Tikvić   added support for...
220
221
  	count := 0
  	success := 0
67337ffa8   Marko Tikvić   payload editing
222
223
224
  	if len(metadata) > 0 {
  		metadata = nil
  	}
2ea67927f   Marko Tikvić   added support for...
225
226
227
228
  	metadata = make(map[string]Payload)
  	for rset.Next() {
  		name := rset.Row[0].(string)
  		load := []byte(rset.Row[1].(string))
8dbe745c3   Marko Tikvić   merged tables uti...
229

2ea67927f   Marko Tikvić   added support for...
230
231
232
  		p := Payload{}
  		err := json.Unmarshal(load, &p)
  		if err != nil {
0e41f4d80   Marko Tikvić   refactored due to...
233
234
235
  			logger.Log("couldn't init: '%s' metadata: %s
  %s
  ", name, err.Error(), rset.Row[1].(string))
2ea67927f   Marko Tikvić   added support for...
236
237
238
  		} else {
  			success++
  			metadata[name] = p
8dbe745c3   Marko Tikvić   merged tables uti...
239
  		}
2ea67927f   Marko Tikvić   added support for...
240
  		count++
8dbe745c3   Marko Tikvić   merged tables uti...
241
  	}
0e41f4d80   Marko Tikvić   refactored due to...
242
243
  	logger.Log("webutility: successfully loaded %d/%d (%.1f%%) entities
  ", success, count, float32(success)/float32(count)*100.0)
8dbe745c3   Marko Tikvić   merged tables uti...
244

2ea67927f   Marko Tikvić   added support for...
245
  	return nil
8dbe745c3   Marko Tikvić   merged tables uti...
246
  }
2ea67927f   Marko Tikvić   added support for...
247
248
249
250
251
252
253
254
255
256
257
258
  func hotload(n int) {
  	entityScan := make(map[string]int64)
  	firstCheck := true
  	for {
  		time.Sleep(time.Duration(n) * time.Second)
  		stmt, err := metadataDB.Prep(`select
  			ora_rowscn,
  			entity_type
  			from entities where projekat = `+fmt.Sprintf("'%s'", activeProject),
  			ora.I64,
  			ora.S)
  		if err != nil {
0e41f4d80   Marko Tikvić   refactored due to...
259
260
  			logger.Log("hotload failed: %v
  ", err)
2ea67927f   Marko Tikvić   added support for...
261
262
  			time.Sleep(time.Duration(n) * time.Second)
  			continue
8dbe745c3   Marko Tikvić   merged tables uti...
263
  		}
8dbe745c3   Marko Tikvić   merged tables uti...
264

2ea67927f   Marko Tikvić   added support for...
265
266
267
268
269
270
271
  		rset, err := stmt.Qry()
  		if err != nil {
  			fmt.Fprintf(os.Stderr, "hotload failed: %v
  ", err)
  			time.Sleep(time.Duration(n) * time.Second)
  			continue
  		}
8dbe745c3   Marko Tikvić   merged tables uti...
272

2ea67927f   Marko Tikvić   added support for...
273
274
275
276
277
278
279
280
  		var toRefresh []string
  		for rset.Next() {
  			scanID := rset.Row[0].(int64)
  			entity := rset.Row[1].(string)
  			oldID, ok := entityScan[entity]
  			if !ok || oldID != scanID {
  				entityScan[entity] = scanID
  				toRefresh = append(toRefresh, entity)
8dbe745c3   Marko Tikvić   merged tables uti...
281
282
  			}
  		}
2ea67927f   Marko Tikvić   added support for...
283
  		stmt.Close()
8dbe745c3   Marko Tikvić   merged tables uti...
284

2ea67927f   Marko Tikvić   added support for...
285
  		if rset.Err() != nil {
0e41f4d80   Marko Tikvić   refactored due to...
286
287
  			logger.Log("hotload rset error: %v
  ", rset.Err())
2ea67927f   Marko Tikvić   added support for...
288
289
290
  			time.Sleep(time.Duration(n) * time.Second)
  			continue
  		}
8dbe745c3   Marko Tikvić   merged tables uti...
291

2ea67927f   Marko Tikvić   added support for...
292
293
294
295
296
297
298
299
  		if len(toRefresh) > 0 && !firstCheck {
  			mu.Lock()
  			refreshMetadata(toRefresh)
  			mu.Unlock()
  		}
  		if firstCheck {
  			firstCheck = false
  		}
8dbe745c3   Marko Tikvić   merged tables uti...
300
  	}
2ea67927f   Marko Tikvić   added support for...
301
  }
8dbe745c3   Marko Tikvić   merged tables uti...
302

2ea67927f   Marko Tikvić   added support for...
303
304
  func refreshMetadata(entities []string) {
  	for _, e := range entities {
67337ffa8   Marko Tikvić   payload editing
305
306
  		fmt.Printf("refreshing %s
  ", e)
2ea67927f   Marko Tikvić   added support for...
307
308
309
310
311
312
  		stmt, err := metadataDB.Prep(`select
  			metadata
  			from entities
  			where projekat = `+fmt.Sprintf("'%s'", activeProject)+
  			` and entity_type = `+fmt.Sprintf("'%s'", e),
  			ora.S)
8dbe745c3   Marko Tikvić   merged tables uti...
313

2ea67927f   Marko Tikvić   added support for...
314
  		if err != nil {
0e41f4d80   Marko Tikvić   refactored due to...
315
316
  			logger.Log("webutility: refresh: prep: %v
  ", err)
2ea67927f   Marko Tikvić   added support for...
317
318
319
  			stmt.Close()
  			continue
  		}
64041a2ea   Marko Tikvić   first commit
320

2ea67927f   Marko Tikvić   added support for...
321
322
323
324
325
326
327
328
329
330
331
332
333
  		rset, err := stmt.Qry()
  		if err != nil {
  			fmt.Printf("webutility: refresh: query: %v
  ", err)
  			stmt.Close()
  			continue
  		}
  
  		for rset.Next() {
  			load := []byte(rset.Row[0].(string))
  			p := Payload{}
  			err := json.Unmarshal(load, &p)
  			if err != nil {
0e41f4d80   Marko Tikvić   refactored due to...
334
335
336
  				logger.Log("couldn't refresh: '%s' metadata: %s
  %s
  ", e, err.Error(), rset.Row[0].(string))
2ea67927f   Marko Tikvić   added support for...
337
338
  			} else {
  				metadata[e] = p
2ea67927f   Marko Tikvić   added support for...
339
340
341
342
  			}
  		}
  		stmt.Close()
  	}
64041a2ea   Marko Tikvić   first commit
343
  }