I've not worked with Asterisk::AMI, but I assume that the reason the send_action method takes a callback method is that the result comes back asynchronously. You can't guarantee how long that will take.
A quick and easy solution is to place the database update inside the callback function like this:
sub do_leave {
my ($asterisk, $event) = @_;
my $get_value = sub {
my ($ast, $resp, $ref_join_id) = @_;
for my $key (keys %$resp) {
if ($key eq "PARSED") {
my $ref_join_id = $resp->{$key}{"Value"};
my $sql = "UPDATE conference_log SET duration=(TIMESTAMPDIFF(SECOND, (SELECT start_conf), NOW())), end_conf=(NOW()) WHERE id=?";
my $sth = $dbh->prepare($sql);
$sth->execute($join_id);
}
}
};
my $id = $astman->send_action({ Action => 'Getvar',
Variable => 'join_id',
Channel => $event->{'Channel'},
}, $get_value);
}
Notice that I have used an anonymous sub, assigned to a variable, which would allow you to share variables between the outer do_leave sub and the callback sub (this is called a closure). However in this case it is probably not needed since there are no shared variables.