AWS Lambda预热函数重新发送代码,如何停止它?

时间:2018-10-20 13:19:05

标签: java amazon-web-services aws-lambda

所以我的代码执行了多次,几乎就像它在代码中返回并以某种方式重新执行一样...

此代码在Intent上执行

@Override
public void onIntent(SpeechletRequestEnvelope<IntentRequest> requestEnvelope, Intent intent, String name) {
    IntentRequest request = requestEnvelope.getRequest();
    switch (request.getDialogState()) {
        case STARTED:
            this.speechletResponse = Response.getDialogueResponse(intent, true);
            break;
        case IN_PROGRESS:
            this.speechletResponse = Response.getDialogueResponse(intent, false);
            break;
        case COMPLETED:
            String numberString = intent.getSlot(SlotTitle.ID).getValue();
            if (!NumberUtils.isCreatable(numberString)) {
                this.speechletResponse = Response.ERROR;
                break;
            }

            Member member = Info.GUILD.getMemberById(numberString);
            User sender = UserDB.getUser(member);

            Future<Ticket> commissionTicket = new CommissionTicket(sender).create();
            try {
                commissionTicket.get(10000, TimeUnit.MILLISECONDS);
            } catch (Exception e) {
                e.printStackTrace();
            }

            SpeechletResponse resp = Response.NEW_TICKED_CREATED;
            resp.setNullableShouldEndSession(true);

            this.speechletResponse = resp;
            break;
    }
}

这是Ticket#create方法,可在同一块上多次运行

public Future<Ticket> create() {
    GuildController guildController = Info.GUILD.getController();
    RequestFuture<Channel> channelRequestFuture = guildController.createTextChannel(ticketType.name().toLowerCase() + "-" + creator.getName() + "-" + id.value()).submit();
    try {
        Channel channel = channelRequestFuture.get(10000, TimeUnit.MILLISECONDS);
        ChannelManager channelManager = channel.getManager();
        GuildManager guildManager = channelManager.getGuild().getManager();
        List<Member> members = guildManager.getGuild().getMembers();
        List<Member> admins = new ArrayList<>();

        for (Member member : members) {
            for (Role role : member.getRoles()) {
                if (!role.getName().equalsIgnoreCase(Info.ADMIN_STRING)) continue;
                admins.add(member);
            }
        }

        for (Member member : members) {
            if (member.equals(creator.getMember())) continue;
            channel.createPermissionOverride(member).setDeny(Permission.MESSAGE_READ).queue();
        }


        for (Member admin : admins) {
            if (admin.equals(creator.getMember())) continue;
            channel.createPermissionOverride(admin).setAllow(Permission.MESSAGE_READ).queue();
        }


        BotMessage botMessage = new BotMessage();
        botMessage
                .setTitle("New Ticket! User: " + creator.getName())
                .setColour(Color.CYAN)
                .setDescription("Please enter your full request here! \n" +
                        "Make sure to let us know whether you are looking for a quote/timeframe,\n" +
                        "or have a budget in mind, and we will work around you!\n\n" +
                        "A sales representative will be with you as soon as possible!")
                .send((TextChannel) channel);


        this.textChannel = (TextChannel) channel;

        TicketDB.addTicket(this);

    } catch (Exception e) {
        e.printStackTrace();
    }

    if (!userIsInTicket(creator)) users.add(creator);
    Future<Ticket> future = ConcurrentUtils.constantFuture(this);
    return future;

}

因此,当Ticket#create代码运行时,它将创建一个唯一的新文本通道,并向该通道发送一条消息。 一切都很好,但是在创建通道之后,我再次调用了lambda函数,因此它是“暖和的”,并且按预期方式创建了一个新的唯一文本通道,但是它还在创建的通道中发送了该消息之前由于未知原因又两次。如果我能得到为什么的帮助,将不胜感激。谢谢

https://gyazo.com/2432b101a051ce2dc6521e939d8a8690

1 个答案:

答案 0 :(得分:1)

我相信您问题的核心是某些变量(通道)存在于处理程序函数之外。

AWS Lambda只是一个Docker容器。有时有时会重新启动容器...但是通常在将其旋转并初始化后,调用“暖” lambda时唯一发生的事情是在现有的运行中调用处理程序函数(由某些外部AWS组件调用)容器...

因此,任何驻留在处理程序函数之外的东西,仅在首次初始化代码时才被调用,并将在后续调用中保留其初始值。

尝试一下(Python示例):

from datetime import datetime

now = str(datetime.now())

def lambda_handler(event, context):
    return now

此代码段将存在于名为lambda_function.py的模块中。首次调用lambda时,将启动带有Python解释器的Docker容器,该容器将加载lambda_function模块并调用lambda_handler()函数。

但是,当您第二次调用该函数时,该模块已经加载。因此now变量已经被初始化,并且它是先前的值。随后对lambda_handler()的调用(如果需要,也可以调用“ lambda函数调用”)将传递与第一次初始化模块时创建的值相同的值。