github.com/moleculer-go/moleculer@v0.3.3/context/contextFactory.go (about) 1 package context 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/moleculer-go/moleculer" 8 "github.com/moleculer-go/moleculer/payload" 9 "github.com/moleculer-go/moleculer/util" 10 11 log "github.com/sirupsen/logrus" 12 ) 13 14 type Context struct { 15 id string 16 requestID string 17 broker *moleculer.BrokerDelegates 18 targetNodeID string 19 sourceNodeID string 20 parentID string 21 actionName string 22 eventName string 23 groups []string 24 broadcast bool 25 params moleculer.Payload 26 meta moleculer.Payload 27 timeout int 28 level int 29 caller string 30 } 31 32 func BrokerContext(broker *moleculer.BrokerDelegates) moleculer.BrokerContext { 33 localNodeID := broker.LocalNode().GetID() 34 id := fmt.Sprint("rootContext-broker-", localNodeID, "-", util.RandomString(12)) 35 context := Context{ 36 id: id, 37 broker: broker, 38 level: 1, 39 parentID: "ImGroot;)", 40 meta: payload.Empty(), 41 } 42 return &context 43 } 44 45 // ChildEventContext : create a child context for a specific event call. 46 func (context *Context) ChildEventContext(eventName string, params moleculer.Payload, groups []string, broadcast bool) moleculer.BrokerContext { 47 parentContext := context 48 meta := parentContext.meta 49 if context.broker.Config.Metrics { 50 meta = meta.Add("tracing", true) 51 } 52 id := util.RandomString(12) 53 var requestID string 54 if parentContext.requestID != "" { 55 requestID = parentContext.requestID 56 } else { 57 requestID = id 58 } 59 caller := parentContext.actionName 60 if parentContext.eventName != "" { 61 caller = parentContext.eventName 62 } 63 eventContext := Context{ 64 id: id, 65 requestID: requestID, 66 broker: parentContext.broker, 67 eventName: eventName, 68 groups: groups, 69 params: params, 70 broadcast: broadcast, 71 level: parentContext.level + 1, 72 meta: meta, 73 parentID: parentContext.id, 74 caller: caller, 75 } 76 return &eventContext 77 } 78 79 // Config return the broker config attached to this context. 80 func (context *Context) BrokerDelegates() *moleculer.BrokerDelegates { 81 return context.broker 82 } 83 84 // ChildActionContext : create a child context for a specific action call. 85 func (context *Context) ChildActionContext(actionName string, params moleculer.Payload, opts ...moleculer.Options) moleculer.BrokerContext { 86 parentContext := context 87 meta := parentContext.meta 88 if context.broker.Config.Metrics { 89 meta = meta.Add("tracing", true) 90 } 91 if len(opts) > 0 && opts[0].Meta != nil && opts[0].Meta.Len() > 0 { 92 meta = meta.AddMany(opts[0].Meta.RawMap()) 93 } 94 id := util.RandomString(12) 95 var requestID string 96 if parentContext.requestID != "" { 97 requestID = parentContext.requestID 98 } else { 99 requestID = id 100 } 101 caller := parentContext.actionName 102 if parentContext.eventName != "" { 103 caller = parentContext.eventName 104 } 105 actionContext := Context{ 106 id: id, 107 requestID: requestID, 108 broker: parentContext.broker, 109 actionName: actionName, 110 params: params, 111 level: parentContext.level + 1, 112 meta: meta, 113 parentID: parentContext.id, 114 caller: caller, 115 } 116 return &actionContext 117 } 118 119 // ActionContext create an action context for remote call. 120 func ActionContext(broker *moleculer.BrokerDelegates, values map[string]interface{}) moleculer.BrokerContext { 121 var level int 122 var timeout int 123 var meta moleculer.Payload 124 125 sourceNodeID := values["sender"].(string) 126 id := values["id"].(string) 127 actionName, isAction := values["action"] 128 if !isAction { 129 panic(errors.New("Can't create an action context, you need a action field!")) 130 } 131 level = values["level"].(int) 132 133 parentID := "" 134 if p, ok := values["parentID"]; ok { 135 if s, ok := p.(string); ok { 136 parentID = s 137 } 138 } 139 // params := payload.Empty() 140 // if values["params"] != nil { 141 // params = payload.New(values["params"]) 142 // } 143 params := payload.New(values["params"]) 144 145 if values["timeout"] != nil { 146 timeout = values["timeout"].(int) 147 } 148 if values["meta"] != nil { 149 meta = payload.New(values["meta"]) 150 } else { 151 meta = payload.Empty() 152 } 153 154 newContext := Context{ 155 broker: broker, 156 sourceNodeID: sourceNodeID, 157 targetNodeID: sourceNodeID, 158 id: id, 159 actionName: actionName.(string), 160 parentID: parentID, 161 params: params, 162 meta: meta, 163 timeout: timeout, 164 level: level, 165 } 166 167 return &newContext 168 } 169 170 // EventContext create an event context for a remote call. 171 func EventContext(broker *moleculer.BrokerDelegates, values map[string]interface{}) moleculer.BrokerContext { 172 var meta moleculer.Payload 173 sourceNodeID := values["sender"].(string) 174 id := "" 175 if t, ok := values["id"]; ok { 176 id = t.(string) 177 } 178 eventName, isEvent := values["event"] 179 if !isEvent { 180 panic(errors.New("Can't create an event context, you need an event field!")) 181 } 182 if values["meta"] != nil { 183 meta = payload.New(values["meta"]) 184 } else { 185 meta = payload.Empty() 186 } 187 newContext := Context{ 188 broker: broker, 189 sourceNodeID: sourceNodeID, 190 id: id, 191 eventName: eventName.(string), 192 broadcast: values["broadcast"].(bool), 193 params: payload.New(values["data"]), 194 meta: meta, 195 } 196 if values["groups"] != nil { 197 temp := values["groups"] 198 aTransformer := payload.ArrayTransformer(&temp) 199 if aTransformer != nil { 200 iArray := aTransformer.InterfaceArray(&temp) 201 sGroups := make([]string, len(iArray)) 202 for index, item := range iArray { 203 sGroups[index] = item.(string) 204 } 205 newContext.groups = sGroups 206 } 207 } 208 return &newContext 209 } 210 211 func (context *Context) IsBroadcast() bool { 212 return context.broadcast 213 } 214 215 func (context *Context) RequestID() string { 216 return context.requestID 217 } 218 219 // AsMap : export context info in a map[string] 220 func (context *Context) AsMap() map[string]interface{} { 221 mapResult := make(map[string]interface{}) 222 223 var tracing bool 224 if context.meta.Get("tracing").Exists() { 225 tracing = context.meta.Get("tracing").Bool() 226 } 227 228 mapResult["id"] = context.id 229 mapResult["requestID"] = context.requestID 230 231 mapResult["level"] = context.level 232 mapResult["meta"] = context.meta.RawMap() 233 mapResult["caller"] = context.caller 234 mapResult["tracing"] = tracing 235 mapResult["parentID"] = context.parentID 236 237 if context.actionName != "" { 238 mapResult["action"] = context.actionName 239 mapResult["timeout"] = context.timeout 240 mapResult["params"] = context.params.Value() 241 } 242 if context.eventName != "" { 243 mapResult["event"] = context.eventName 244 mapResult["groups"] = context.groups 245 mapResult["broadcast"] = context.broadcast 246 mapResult["data"] = context.params.Value() 247 mapResult["level"] = context.level 248 } 249 250 //streaming not supported yet 251 mapResult["stream"] = false 252 //mapResult["seq"] = 0 // for stream payloads 253 254 return mapResult 255 } 256 257 func (context *Context) MCall(callMaps map[string]map[string]interface{}) chan map[string]moleculer.Payload { 258 return context.broker.MultActionDelegate(callMaps) 259 } 260 261 // Call : main entry point to call actions. 262 // chained action invocation 263 func (context *Context) Call(actionName string, params interface{}, opts ...moleculer.Options) chan moleculer.Payload { 264 actionContext := context.ChildActionContext(actionName, payload.New(params), opts...) 265 return context.broker.ActionDelegate(actionContext, opts...) 266 } 267 268 // Emit : Emit an event (grouped & balanced global event) 269 func (context *Context) Emit(eventName string, params interface{}, groups ...string) { 270 context.Logger().Debug("Context Emit() eventName: ", eventName) 271 newContext := context.ChildEventContext(eventName, payload.New(params), groups, false) 272 context.broker.EmitEvent(newContext) 273 } 274 275 // Broadcast : Broadcast an event for all local & remote services 276 func (context *Context) Broadcast(eventName string, params interface{}, groups ...string) { 277 newContext := context.ChildEventContext(eventName, payload.New(params), groups, true) 278 context.broker.BroadcastEvent(newContext) 279 } 280 281 func (context *Context) WaitFor(services ...string) error { 282 return context.broker.WaitFor(services...) 283 } 284 285 func (context *Context) Publish(services ...interface{}) { 286 context.broker.Publish(services...) 287 } 288 289 func (context *Context) ActionName() string { 290 return context.actionName 291 } 292 293 func (context *Context) EventName() string { 294 return context.eventName 295 } 296 297 func (context *Context) Groups() []string { 298 return context.groups 299 } 300 301 func (context *Context) Payload() moleculer.Payload { 302 return context.params 303 } 304 305 func (context *Context) SetTargetNodeID(targetNodeID string) { 306 context.Logger().Debug("context factory SetTargetNodeID() targetNodeID: ", targetNodeID) 307 context.targetNodeID = targetNodeID 308 } 309 310 func (context *Context) TargetNodeID() string { 311 return context.targetNodeID 312 } 313 314 func (context *Context) SourceNodeID() string { 315 return context.sourceNodeID 316 } 317 318 func (context *Context) ID() string { 319 return context.id 320 } 321 322 func (context *Context) Meta() moleculer.Payload { 323 return context.meta 324 } 325 326 func (context *Context) UpdateMeta(meta moleculer.Payload) { 327 context.meta = meta 328 } 329 330 func (context *Context) Logger() *log.Entry { 331 if context.actionName != "" { 332 return context.broker.Logger("action", context.actionName) 333 } 334 if context.eventName != "" { 335 return context.broker.Logger("event", context.eventName) 336 } 337 return context.broker.Logger("context", "<root>") 338 } 339 340 func (context *Context) Caller() string { 341 return context.caller 342 }