예제 #1
0
func (resource *LeverResource) closeInternal(soft bool) {
	if resource.closing {
		return
	}
	resource.closing = true

	resource.expiryTimer.Stop()
	resource.sessionKAB.Close()

	// TODO: Is it ok to hold lock while doing RPC within container?
	//       What happens if call takes a really long time?
	// Send RPC inside container to tell that resource closed.
	if !soft {
		conn, err := resource.conns.Dial(resource.instanceAddr)
		if err != nil {
			resource.logger.WithFields("err", err).Error(
				"Failed to dial in Lever instance")
			go resource.onCloseFun(resource.leverResource, err)
			return
		}
		leverURL := &core.LeverURL{
			Environment: resource.leverEnv,
			Service:     resource.leverService,
			Method:      "CloseResource",
		}
		_, err = core.SendLeverRPC(
			conn, context.Background(), leverURL, &core.RPC{
				ArgsOneof: &core.RPC_Args{
					Args: &core.JSONArray{
						Element: []*core.JSON{{
							JsonValueOneof: &core.JSON_JsonString{
								JsonString: resource.leverResource,
							},
						}},
					},
				},
			})
		if err != nil {
			resource.logger.WithFields("err", err).Error(
				"Failed resource close call")
			go resource.onCloseFun(resource.leverResource, err)
			return
		}
	}

	// Async so as not to hog the lock.
	go func() {
		err := resource.levResResource.Deregister()
		if err != nil {
			resource.logger.WithFields("err", err).Debug(
				"Resource lock deregister error")
		}
	}()

	go resource.onCloseFun(resource.leverResource, nil)
}
예제 #2
0
func (resource *LeverResource) construct() error {
	// TODO: Is it ok to hold lock while doing RPC within container?
	//       What happens if call takes a really long time?
	// Send RPC to instance to inform that it will be hosting this resource.
	resource.lock.Lock()
	defer resource.lock.Unlock()
	conn, err := resource.conns.Dial(resource.instanceAddr)
	if err != nil {
		resource.logger.WithFields("err", err).Error(
			"Failed to dial in Lever instance")
		return err
	}
	leverURL := &core.LeverURL{
		Environment: resource.leverEnv,
		Service:     resource.leverService,
		Method:      "NewResource",
	}
	_, err = core.SendLeverRPC(
		conn, context.Background(), leverURL, &core.RPC{
			ArgsOneof: &core.RPC_Args{
				Args: &core.JSONArray{
					Element: []*core.JSON{{
						JsonValueOneof: &core.JSON_JsonString{
							JsonString: resource.leverResource,
						},
					}},
				},
			},
		})
	if err != nil {
		resource.logger.WithFields("err", err).Error(
			"Failed resource construct call")
		return err
	}
	return nil
}
예제 #3
0
func (client *Client) invokeInternal(
	replyObj interface{}, leverURL *core.LeverURL,
	args ...interface{}) (err error) {
	if IsChanMethod(leverURL.Method) {
		return fmt.Errorf(
			"Use InvokeChan / InvokeChanURL for streaming methods")
	}
	if leverURL.Environment == "" && OwnEnvironment == "" {
		return fmt.Errorf(
			"Environment not specified and cannot be deduced")
	}
	if leverURL.Environment == "" {
		leverURL.Environment = OwnEnvironment
	}

	var dialTo string
	if client.ForceHost != "" {
		dialTo = client.ForceHost
	} else {
		if (core.IsInternalEnvironment(leverURL.Environment) ||
			leverURL.Environment == OwnEnvironment) &&
			internalRPCGateway != "" {
			dialTo = internalRPCGateway
		} else {
			dialTo = leverURL.Environment
		}
	}
	conn, err := client.conns.Dial(dialTo)
	if err != nil {
		return err
	}

	rpc := &core.RPC{}
	if len(args) == 1 {
		byteArgs, ok := args[0].([]byte)
		if ok {
			// Byte args case.
			rpc.ArgsOneof = &core.RPC_ByteArgs{
				ByteArgs: byteArgs,
			}
		}
	}
	if rpc.ArgsOneof == nil {
		// Non-byte args case.
		var encdArgs *core.JSONArray
		encdArgs, err = encodeArgs(args)
		if err != nil {
			return err
		}
		rpc.ArgsOneof = &core.RPC_Args{
			Args: encdArgs,
		}
	}
	reply, err := core.SendLeverRPC(
		conn, context.Background(), leverURL, rpc)
	if err != nil {
		return err
	}

	if reply.GetResultOneof() == nil {
		return fmt.Errorf("Received nil result oneof")
	}
	switch result := reply.GetResultOneof().(type) {
	case *core.RPCReply_ByteResult:
		byteReplyObj, ok := replyObj.(*[]byte)
		if !ok {
			return fmt.Errorf(
				"replyObj needs to be type *[]byte when RPC returns bytes")
		}
		*byteReplyObj = result.ByteResult
		return nil
	case *core.RPCReply_ByteError:
		return &RemoteByteError{Err: result.ByteError}
	case *core.RPCReply_Result:
		return decodeArgAsValue(result.Result, replyObj)
	case *core.RPCReply_Error:
		return &RemoteError{Err: buildDataForJSON(result.Error)}
	default:
		return fmt.Errorf("Invalid type")
	}
}