예제 #1
0
func (sc *SocketCrutch) createClient(ws *websocket.Conn, req *http.Request) {
	id := xid.New().String()

	conn := newConnection(ws, sc)
	session := newSession(conn, id, req, sc)

	atomic.AddInt32(&sc.connectCounter, 1)
	defer atomic.AddInt32(&sc.connectCounter, -1)

	log.Debugf("the client session #%s created, the current number of connections %d", id, sc.connectCounter)

	if sc.connectHandler != nil {
		sc.connectHandler(session)
	}

	// Start reading and writing the goroutines.
	conn.run()
	// Wait disconnect
	conn.wait()

	if sc.disconnectHandler != nil {
		sc.disconnectHandler(session)
	}

	log.Debugf("the client session #%s disconnected, the current number of connections %d", id, sc.connectCounter)
}
예제 #2
0
func (api *RestMessageAPI) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, `Can not read body`, http.StatusBadRequest)
		return
	}

	topic, err := api.extractTopic(r.URL.Path)
	if err != nil {
		if err == errNotFound {
			http.NotFound(w, r)
			return
		}
		http.Error(w, "Server error.", http.StatusInternalServerError)
		return
	}

	msg := &protocol.Message{
		Path:          protocol.Path(topic),
		Body:          body,
		UserID:        q(r, `userId`),
		ApplicationID: xid.New().String(),
		OptionalID:    q(r, `messageId`),
		HeaderJSON:    headersToJSON(r.Header),
		NodeID:        *config.Cluster.NodeID,
	}

	api.router.HandleMessage(msg)
}
func init() {
	funcMap = template.FuncMap{
		"isNil":        isNil,
		"getJSON":      getJSON,
		"getenv":       func(varName string) string { return os.Getenv(varName) },
		"replaceMaps":  replaceMaps,
		"replace":      replace,
		"regexCompile": regexp.Compile,
		"substr":       substr,
		"split":        split,
		"in":           in,
		"toStr":        toStr,
		"dateFormat":   dateFormat,
		"now":          time.Now,
		"localtime":    time.Now().Local,
		"newDict":      newDict,
		"newArray":     newArray,
		"scanf":        fmt.Sscanf,
		"exist":        exist,
		"add":          func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '+') },
		"sub":          func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '-') },
		"div":          func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '/') },
		"xid":          xid.New().String,
	}
}
예제 #4
0
func NewHttpJsonApiPayload() (payload *HttpJsonApiPayload) {
	payload = &HttpJsonApiPayload{
		id:      xid.New().String(),
		context: make(spirit.Map),
	}

	return
}
예제 #5
0
// NewWebSocket returns a new WebSocket.
func NewWebSocket(handler *WSHandler, wsConn WSConnection, userID string) *WebSocket {
	return &WebSocket{
		WSHandler:     handler,
		WSConnection:  wsConn,
		applicationID: xid.New().String(),
		userID:        userID,
		sendChannel:   make(chan []byte, 10),
		receivers:     make(map[protocol.Path]*Receiver),
	}
}
예제 #6
0
func (p *TaskManager) NewTask(task models.Task) (id string, err error) {

	task.Id = xid.New().String()
	task.CreateTime = time.Now()
	task.UpdateTime = time.Now()

	p.tasks[task.Id] = &task

	id = task.Id

	return
}
예제 #7
0
파일: datastore.go 프로젝트: jmank88/todo
// The Put method inserts task into the tasks table.
func (d *dataStore) Put(task task.Task) (string, error) {
	db, err := d.db()
	if err != nil {
		return "", err
	}
	if task.ID == "" {
		// No id, so generate a random id.
		task.ID = xid.New().String()
	}
	_, err = db.Exec("INSERT INTO tasks (id, title, content) VALUES ($1, $2, $3)", task.ID, task.Title, task.Description)
	return task.ID, err
}
예제 #8
0
func NewWSHandler(messageSouce PubSubSource, messageSink MessageSink, messageStore store.MessageStore, wsConn WSConn, userId string) *WSHandler {
	server := &WSHandler{
		messageSouce:  messageSouce,
		messageSink:   messageSink,
		messageStore:  messageStore,
		clientConn:    wsConn,
		applicationId: xid.New().String(),
		userId:        userId,
		sendChannel:   make(chan []byte, 10),
		receiver:      make(map[guble.Path]*Receiver),
	}
	return server
}
// Login perform a login using a password and user id returning the security token if successful
func (d DefaultSec) Login(dbConn *sql.DB, id string, psw string) (string, error) {
	logit.Info.Println("DefaultSec.Login")
	var uuid string
	var err error
	var user User
	var unencryptedPsw string
	user, err = DBGetUser(dbConn, id)
	if err != nil {
		if err == sql.ErrNoRows {
			logit.Error.Println(err.Error())
			return "", errors.New("user not found")
		} else {
			logit.Error.Println(err.Error())
			return "", err
		}
	}
	logit.Info.Println("Login checkpoint 1")

	unencryptedPsw, err = DecryptPassword(user.Password)
	if err != nil {
		logit.Error.Println(err.Error())
		return "", err
	}

	if unencryptedPsw != psw {
		return "", errors.New("incorrect password")
	}
	logit.Info.Println("Login checkpoint 2")

	/**
	uuid, err = newUUID()
	if err != nil {
		logit.Error.Println(err.Error())
		return "", err
	}
	*/
	guid := xid.New()
	uuid = guid.String()

	logit.Info.Println("Login checkpoint 3")
	//register the session
	err = DBAddSession(dbConn, uuid, id)
	if err != nil {
		logit.Error.Println(err.Error())
		return "", err
	}

	logit.Info.Println("secimpl Login returning uuid " + uuid)
	return uuid, nil
}
예제 #10
0
func (api *RestMessageApi) PostMessage(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, `Can not read body`, http.StatusBadRequest)
		return
	}

	msg := &guble.Message{
		Path:                   guble.Path(params.ByName(`topic`)),
		Body:                   body,
		PublisherUserId:        q(r, `userId`),
		PublisherApplicationId: xid.New().String(),
		PublisherMessageId:     q(r, `messageId`),
		HeaderJson:             headersToJson(r.Header),
	}

	api.MessageSink.HandleMessage(msg)
}
예제 #11
0
파일: handler.go 프로젝트: patrickToca/xlog
// RequestIDHandler returns a handler setting a unique id to the request which can
// be gathered using IDFromContext(ctx). This generated id is added as a field to the
// logger using the passed name as field name. The id is also added as a response
// header if the headerName is not empty.
//
// The generated id is a URL safe base64 encoded mongo object-id-like unique id.
// Mongo unique id generation algorithm has been selected as a trade-off between
// size and ease of use: UUID is less space efficient and snowflake requires machine
// configuration.
func RequestIDHandler(name, headerName string) func(next xhandler.HandlerC) xhandler.HandlerC {
	return func(next xhandler.HandlerC) xhandler.HandlerC {
		return xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
			id, ok := IDFromContext(ctx)
			if !ok {
				id = xid.New()
				ctx = context.WithValue(ctx, idKey, id)
			}
			if name != "" {
				FromContext(ctx).SetField(name, id)
			}
			if headerName != "" {
				w.Header().Set(headerName, id.String())
			}
			next.ServeHTTPC(ctx, w, r)
		})
	}
}
예제 #12
0
파일: handler.go 프로젝트: snyderep/pongish
func (p *PongishHandlerProvider) screenHandler(w http.ResponseWriter, r *http.Request) {
	// Get a session. Get() always returns a session, even if empty.
	session, err := store.Get(r, "pongish-a")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	if session.IsNew {
		guid := xid.New()
		session.Values["id"] = guid.String()
	}

	data := make(map[string]interface{})
	data["WsGameEndpoint"] = p.wsGameEndpoint

	if err := p.renderer.renderTemplate(w, "_screen.tmpl", data); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}
예제 #13
0
파일: handler.go 프로젝트: rs/xlog
// RequestIDHandler returns a handler setting a unique id to the request which can
// be gathered using IDFromContext(ctx). This generated id is added as a field to the
// logger using the passed name as field name. The id is also added as a response
// header if the headerName is not empty.
//
// The generated id is a URL safe base64 encoded mongo object-id-like unique id.
// Mongo unique id generation algorithm has been selected as a trade-off between
// size and ease of use: UUID is less space efficient and snowflake requires machine
// configuration.
func RequestIDHandler(name, headerName string) func(next http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			ctx := r.Context()
			id, ok := IDFromContext(ctx)
			if !ok {
				id = xid.New()
				ctx = context.WithValue(ctx, idKey, id)
				r = r.WithContext(ctx)
			}
			if name != "" {
				FromContext(ctx).SetField(name, id)
			}
			if headerName != "" {
				w.Header().Set(headerName, id.String())
			}
			next.ServeHTTP(w, r)
		})
	}
}
예제 #14
0
// ServeHTTP is an http.Handler.
// It is a part of the service.endpoint implementation.
func (api *RestMessageAPI) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Method == http.MethodHead {
		return
	}

	if r.Method == http.MethodGet {
		log.WithField("url", r.URL.Path).Debug("GET")

		topic, err := api.extractTopic(r.URL.Path, subscribersPrefix)
		if err != nil {
			log.WithError(err).Error("Extracting topic failed")
			if err == errNotFound {
				http.NotFound(w, r)
				return
			}
			http.Error(w, "Server error.", http.StatusInternalServerError)
			return
		}

		resp, err := api.router.GetSubscribersForTopic(topic)
		w.Header().Set("Content-Type", "application/json")

		_, err = w.Write(resp)
		if err != nil {
			log.WithField("error", err.Error()).Error("Writing to byte stream failed")
			http.Error(w, "Server error.", http.StatusInternalServerError)
			return
		}
		return
	}

	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "Can not read body", http.StatusBadRequest)
		return
	}

	topic, err := api.extractTopic(r.URL.Path, "/message")
	if err != nil {
		if err == errNotFound {
			http.NotFound(w, r)
			return
		}
		http.Error(w, "Server error.", http.StatusInternalServerError)
		return
	}

	msg := &protocol.Message{
		Path:          protocol.Path(topic),
		Body:          body,
		UserID:        q(r, "userId"),
		ApplicationID: xid.New().String(),
		HeaderJSON:    headersToJSON(r.Header),
	}

	// add filters
	api.setFilters(r, msg)

	api.router.HandleMessage(msg)
	fmt.Fprintf(w, "OK")
}
예제 #15
0
// this call performs 2 tasks:
// 1. if the request body contains a valid job (with an id) the job will be stored on disk [optional]
// 2. (then) it creates a new default job with a new unique id and a unique name and returns it [always]
func (jts *JobTypeServer) handleJobPost(eh *errHandler_T, //--baseDir string,
	c *gin.Context) error {
	var (
		jobTypeName = c.Param("jobType")
		newJobId    = c.Query("newJobId")
		newJobName  = c.Query("newJobName")
	)
	log.Info("job post", "type", jobTypeName, "new-id", newJobId)
	if newJobId != "" {
		return errors.New("POST does not allow to ask for new job id: " + newJobId)
	}

	job, _ /*body_s*/ := readJsonJob(eh, c.Request.Body)

	if job == nil {
		log.Info("posted job EMPTY - not stored")
	} else {
		err := job.Check(jobTypeName, "")
		if err == nil {
			job.storeYamlScript(eh, jts.baseDir)
		} else {
			log.Info("posted job invalid - not stored",
				"id", job.Id, "type", job.TypeName, "name", job.Name,
				"nodes", len(job.Nodes), "err", err.Error())
		}
	}

	newJob := Job{
		TypeName: jobTypeName,
		Id:       "default",
		Name:     newJobName,
	}
	defaultJob, err := newJob.loadYamlScript(eh, jts.baseDir)

	//	Job struct {
	//		TypeName       string                 `json:"type_name,omitempty"`
	//		Id             string                 `json:"job_id,omitempty"`
	//		Name           string                 `json:"job_name,omitempty"`
	//		JsonSha1       string                 `json:"json_id,omitempty"`
	//		YamlSha1       string                 `json:"yaml_id,omitempty"`
	//		Cmd            string                 `json:"cmd,omitempty"`
	//		ScriptTemplate string                 `json:"script_template,omitempty"`
	//		ScriptFPath    string                 `json:"script_fpath,omitempty"`
	//		Debug          map[string]interface{} `json:"debug,omitempty"`
	//		Nodes          []Wrap                 `json:"root"`
	//		DefaultNodes   []Wrap                 `json:"default_root,omitempty"`
	//	}

	if err != nil || defaultJob == nil {
		defJob, ok := jts.defaults_m[job.TypeName]
		if ok /*&& defJob != nil*/ {
			defaultJob = &defJob
		}
		//		err = nil
	}

	if /*err != nil ||*/ defaultJob == nil {
		log.Error("NO Default Job", "err", err)
		panic("NO Default Job")
		//		newJob.Nodes = job.DefaultNodes
		//		newJob.ScriptTemplate = job.ScriptTemplate
		//		log.Info("using hardcoded default job",
		//			"job.nodes", len(newJob.Nodes),
		//			"job.defaultNodes", len(newJob.DefaultNodes))
	} else {
		newJob = *defaultJob
		log.Info("using loaded default job",
			"job.nodes", len(newJob.Nodes),
		//			"job.defaultNodes", len(newJob.DefaultNodes)
		)
	}
	newJob.Id = xid.New().String()
	idLen4 := len(newJob.Id) - 4
	idTail := newJob.Id[idLen4:]

	if newJob.Name == "" {
		newJob.Name = "new"
	}
	newJob.Name += "-" + idTail

	//	log.Trace("constructed new job", "job", newJob)

	eh.safe(
		func() {
			newJob.log()
			eh.err = newJob.Check(jobTypeName, "")
		},
		func() { newJob.storeYamlScript(eh, jts.baseDir) },
		func() { c.JSON(http.StatusCreated, newJob) },
	)

	eh.ifErr(func() { c.AbortWithError(http.StatusBadRequest, eh.err) })
	return eh.err
}
예제 #16
0
func (p *JsonApiReceiver) toDeliveries(req *gohttp.Request) (deliveries []spirit.Delivery, apiIds map[string]string, err error) {
	isMultiCall := req.Header.Get(p.conf.HeaderDefines.MultiCallHeader) == "1" ||
		req.Header.Get(p.conf.HeaderDefines.MultiCallHeader) == "on" ||
		req.Header.Get(p.conf.HeaderDefines.MultiCallHeader) == "true"

	isForwarded := req.Header.Get(HeaderForwardedPayload) == "1" ||
		req.Header.Get(HeaderForwardedPayload) == "on" ||
		req.Header.Get(HeaderForwardedPayload) == "true"

	if isMultiCall == true && isForwarded == true {
		err = ErrNotSupportMultiCallForward.New()
		return
	}

	idMapping := make(map[string]string)

	var body []byte
	if body, err = ioutil.ReadAll(req.Body); err != nil {
		return
	}

	var apiDatas map[string]interface{} = make(map[string]interface{})

	if isMultiCall {
		if err = json.Unmarshal(body, &apiDatas); err != nil {
			return
		}
	} else {

		apiName := req.Header.Get(p.conf.HeaderDefines.ApiHeader)

		if apiName == "" {
			if p.conf.Path != req.RequestURI {
				apiName = strings.TrimPrefix(req.RequestURI, p.conf.Path)
				apiName = strings.TrimRight(apiName, "/")
			}
		}

		if apiName == "" {
			err = ErrApiNameIsEmpty
			return
		}

		if isForwarded {
			apiData := JsonPayload{}
			if json.Unmarshal(body, &apiData); err != nil {
				return
			}
			apiDatas[apiName] = apiData
		} else {
			var apiData map[string]interface{}
			if json.Unmarshal(body, &apiData); err != nil {
				return
			}
			apiDatas[apiName] = apiData
		}

	}

	var tmpDeliveries []spirit.Delivery
	for api, apiData := range apiDatas {

		payload := NewHttpJsonApiPayload()

		if isForwarded {
			if jsonPayload, ok := apiData.(JsonPayload); ok {
				payload.id = jsonPayload.Id
				payload.data = jsonPayload.Data
				payload.context = jsonPayload.Context
				payload.errs = jsonPayload.Errors
			}
		} else {
			payload.SetData(apiData)

			headerContext := map[string]interface{}{}
			cookiesContext := map[string]interface{}{}

			for _, key := range p.conf.ToContext.Headers {
				if req.Header.Get(key) != "" {
					headerContext[key] = req.Header.Get(key)
				}
			}

			for _, key := range p.conf.ToContext.Cookies {
				if cookie, e := req.Cookie(key); e == nil {
					cookiesContext[cookie.Name] = cookie
				}
			}

			if len(cookiesContext) > 0 {
				payload.SetContext(CtxHttpCookies, cookiesContext)
			}

			if len(headerContext) > 0 {
				payload.SetContext(CtxHttpHeaders, headerContext)
			}

			if len(p.conf.ToContext.Customs) > 0 {
				payload.SetContext(CtxHttpCustom, p.conf.ToContext.Customs)
			}
		}

		deliveryURN := ""
		if urn, exist := p.conf.ApiURN[api]; exist {
			deliveryURN = urn
		} else {
			deliveryURN = p.conf.BindURN
		}

		labels := spirit.Labels{}
		if p.conf.DefaultLabels != nil {
			for k, v := range p.conf.DefaultLabels {
				labels[k] = v
			}
		}

		if apiLabels, exist := p.conf.ApiLabels[api]; exist {
			for k, v := range apiLabels {
				labels[k] = v
			}
		}

		metadata := map[string]interface{}{}

		if p.conf.DefaultMetadata != nil {
			for k, v := range p.conf.DefaultMetadata {
				metadata[k] = v
			}
		}

		if apiMetadata, exist := p.conf.ApiMetadata[api]; exist {
			for k, v := range apiMetadata {
				metadata[k] = v
			}
		}

		de := &HttpJsonApiDelivery{
			id:        xid.New().String(),
			payload:   payload,
			urn:       deliveryURN,
			labels:    labels,
			timestamp: time.Now(),
			metadata:  metadata,
		}

		tmpDeliveries = append(tmpDeliveries, de)

		idMapping[de.id] = api
	}

	deliveries = tmpDeliveries
	apiIds = idMapping

	return
}
예제 #17
0
func (p *MNSSender) callFlow(delivery spirit.Delivery, flowMetadata *MNSFlowMetadata) {
	if flowMetadata == nil {
		return
	}

	sendDeliveryFunc := func(ignoreSendError bool, delivery spirit.Delivery, queueURN map[string]string, queues ...string) (err error) {
		if queues == nil || len(queues) == 0 {
			return
		}

		backupURN := delivery.URN()
		backupParallel := new(MNSParallelFlowMetadata)
		delivery.Payload().Context().Object(mnsSenderQueueParallelIdContext, backupParallel)

		// recover
		defer func() {
			delivery.SetURN(backupURN)
			delivery.Payload().SetContext(mnsSenderQueueParallelIdContext, backupParallel)
		}()

		for _, q := range queues {

			if q == "" {
				continue
			}

			parallelQueues := strings.Split(q, "||")
			parallelCount := len(parallelQueues)
			parallelQueuePid := ""

			if parallelCount > 0 {
				parallelQueuePid = xid.New().String()
			}

			for index, queue := range parallelQueues {

				// recover
				delivery.SetURN(backupURN)
				delivery.Payload().SetContext(mnsSenderQueueParallelIdContext, backupParallel)

				urn := ""
				if queueURN != nil {
					urn, _ = queueURN[queue]
				}

				buf := bytes.Buffer{}
				delivery.SetURN(urn)

				if parallelCount > 0 {
					delivery.Payload().SetContext(mnsSenderQueueParallelIdContext, MNSParallelFlowMetadata{Id: parallelQueuePid, Index: index, Count: parallelCount})
				}

				if err = p.translator.Out(&buf, delivery); err != nil {
					spirit.Logger().
						WithField("actor", spirit.ActorSender).
						WithField("urn", mnsSenderURN).
						WithField("event", "translate delivery").
						Errorln(err)
					return
				} else {
					reqData := ali_mns.MessageSendRequest{
						MessageBody:  ali_mns.Base64Bytes(buf.Bytes()),
						DelaySeconds: int64(p.conf.DelaySeconds),
						Priority:     int64(p.conf.Priority),
					}

					client := p.getMNSClient(queue)
					if _, err = client.SendMessage(reqData); err != nil {

						spirit.Logger().
							WithField("actor", spirit.ActorSender).
							WithField("urn", mnsSenderURN).
							WithField("event", "send mns message").
							Errorln(err)

						if ignoreSendError {
							err = nil
							continue
						}
						return
					}
				}
			}

		}
		return
	}

	currentQueueURN := map[string]string{}
	if err := delivery.Metadata().Object(mnsSenderQueueURNMetadata, &currentQueueURN); err != nil {
		spirit.Logger().
			WithField("actor", spirit.ActorSender).
			WithField("urn", mnsSenderURN).
			WithField("event", "get queue urn").
			Errorln(err)
	}

	if delivery.Payload().LastError() != nil {
		// run error flow

		if flowMetadata.Error != nil && len(flowMetadata.Error) > 0 {

			queueURN := map[string]string{}

			for _, queue := range flowMetadata.Error {
				if urn, exist := currentQueueURN[queue]; exist {
					queueURN[queue] = urn
				}
			}

			delivery.SetMetadata(mnsSenderFlowMetadata, nil)
			sendDeliveryFunc(true, delivery, queueURN, flowMetadata.Error...)
		}

	} else {
		// run normal flow
		if flowMetadata.Normal != nil && len(flowMetadata.Normal) > 0 {
			nextQueue := flowMetadata.Normal[flowMetadata.CurrentFlowId]

			queueURN := map[string]string{}

			if len(flowMetadata.Normal) > flowMetadata.CurrentFlowId {
				tmpRemainQueues := flowMetadata.Normal[flowMetadata.CurrentFlowId:]

				remainQueues := []string{}
				for _, queue := range tmpRemainQueues {
					queues := strings.Split(queue, "||")
					remainQueues = append(remainQueues, queues...)
				}

				for _, queue := range remainQueues {
					if urn, exist := currentQueueURN[queue]; exist {
						queueURN[queue] = urn
					}
				}
			}

			flowMetadata.CurrentFlowId += 1
			defer func() { flowMetadata.CurrentFlowId -= 1 }()

			delivery.SetMetadata(mnsSenderFlowMetadata, flowMetadata)
			sendDeliveryFunc(false, delivery, queueURN, nextQueue)
		}
	}
}
예제 #18
0
파일: id.go 프로젝트: rs/rest-layer
// newID returns a new globally unique id using a copy of the mgo/bson algorithm.
func newID() string {
	return xid.New().String()
}
예제 #19
0
파일: output.go 프로젝트: patrickToca/xlog
// NewUIDOutput returns an output filter adding a globally unique id (using github.com/rs/xid)
// to all message going thru this output. The o parameter defines the next output to pass data
// to.
func NewUIDOutput(field string, o Output) Output {
	return OutputFunc(func(fields map[string]interface{}) error {
		fields[field] = xid.New().String()
		return o.Write(fields)
	})
}
예제 #20
0
파일: aop.go 프로젝트: gogap/aop
func (p *AOP) funcWrapper(bean *Bean, methodName string, methodType reflect.Type) func([]reflect.Value) []reflect.Value {
	beanValue := reflect.ValueOf(bean.instance)

	return func(inputs []reflect.Value) (ret []reflect.Value) {
		callID := xid.New().String()

		var err error
		defer func() {
			if err != nil {
				panic(err)
			}
		}()

		var args Args

		for _, arg := range inputs {
			args = append(args, arg.Interface())
		}

		joinPoint := JoinPoint{
			callID: callID,
			args:   args,
			target: bean,
		}

		errOutIndex := -1
		outLen := methodType.NumOut()

		if outLen > 0 {
			for i := 0; i < outLen; i++ {
				if methodType.Out(i) == errorType {
					errOutIndex = i
				}
			}
		}

		ret = make([]reflect.Value, outLen)
		for i := 0; i < outLen; i++ {
			ret[i] = reflect.Zero(methodType.Out(i))
		}

		var advicesGroup []map[AdviceOrdering][]*Advice
		for _, aspect := range p.aspects {
			var advices map[AdviceOrdering][]*Advice
			if advices, err = aspect.GetMatchedAdvices(bean, methodName, args); err != nil {
				return
			}

			advicesGroup = append(advicesGroup, advices)
		}

		callAdvicesFunc := func(order AdviceOrdering, resultValues ...reflect.Value) (e error) {

			for _, advices := range advicesGroup {
				if e = invokeAdvices(&joinPoint, advices[order], methodName, resultValues); e != nil {
					if errOutIndex >= 0 {
						ret[errOutIndex] = reflect.ValueOf(&e).Elem()
					}
					err = e
					return
				}
			}
			return
		}

		//@Before
		if err = callAdvicesFunc(Before); err != nil {
			return
		}

		//@Real func
		var retValues []reflect.Value

		funcInSturctName := getFuncNameByStructFuncName(methodName)

		realFunc := func(args ...interface{}) Result {
			values := []reflect.Value{}
			for _, arg := range args {
				values = append(values, reflect.ValueOf(arg))
			}

			return beanValue.MethodByName(funcInSturctName).Call(values)
		}

		//@Around
		var aroundAdvice *Advice
		for _, advices := range advicesGroup {
			if aroundAdvices, exist := advices[Around]; exist && len(aroundAdvices) > 0 {
				aroundAdvice = aroundAdvices[0]
				break
			}
		}

		if aroundAdvice != nil {
			pjp := ProceedingJoinPoint{JoinPointer: &joinPoint, method: realFunc}

			if err = invokeAdvices(&pjp, []*Advice{aroundAdvice}, methodName, nil); err != nil {
				if errOutIndex >= 0 {
					ret[errOutIndex] = reflect.ValueOf(&err).Elem()
				}
				return
			}
		} else {
			retValues = realFunc(inputs)
		}

		if IsTracing() {
			var metadata MethodMetadata
			if metadata, err = bean.methodMetadata(funcInSturctName); err != nil {
				return
			}

			appendTraceItem(callID, metadata.File, metadata.Line, "*"+funcInSturctName, methodName, bean.id)
		}

		defer func() {
			//@AfterPanic
			if e := recover(); e != nil {
				callAdvicesFunc(AfterPanic)
			}

			//@After
			callAdvicesFunc(After)
		}()

		if err != nil {
			//@AfterError
			callAdvicesFunc(AfterError)
		} else {
			//@AfterReturning
			callAdvicesFunc(AfterReturning, retValues...)
		}

		return retValues
	}
}