Commit b3f1275cdad84845a70b20f51afd17937363c502

Authored by Marko Tikvić
1 parent 776b4c95bd
Exists in master

refactored middleware

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