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  }