question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

send will not fire when targeting a single user, unless explicitly call Fulture.get() . Under version 0.14.1

See original GitHub issue

I am following instructions from The Best Practice, and introduced Semaphore to control the flow. The sending part is exactly the same as in The Best Practice:

semaphore.acquire();
final CompletableFuture<PushNotificationResponse> sendFuture = apnsClient.sendNotification(pushNotificationSource.next());
sendFuture.whenComplete((response, cause) -> {
    // Do whatever processing needs to be done
    semaphore.release();
});

When targeting for a group of users, it works perfectly well. But when pushing only to one user, it did not work: action in whenComplete() never get called, and the IOS device never get the message.

Further tries show that if we call Future.get(), it would work:

apnsClient.sendNotification(pushNotificationSource.next()).get();

We tried to add break point in the code, and found that this.channelPool.acquire().addListener(...) in function ApnsClient.sendNotification() would not callback if Future.get() is not called. We also tried to push to just 2 user, the first we call Future.get(), the second we do not, and both user can get the message:

AtomicInteger count = new AtomicInteger(0);

......

if (count.incrementAndGet() == 1) {
    apnsClient.sendNotification(pushNotificationSource.next()).get();
} else {
    apnsClient.sendNotification(pushNotificationSource.next());
}

Thanks in advance.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:13 (5 by maintainers)

github_iconTop GitHub Comments

3reactions
jchamberscommented, Sep 10, 2020

Ah—I see what’s happening here. This is most definitely not a bug and is, I think, what I originally suspected.

The problem is that you’re starting a process that will complete some time in the future—sending a push notification and getting the reply—but are shutting down the JVM before that process has time to complete. You must somehow wait for the operation to complete if you want to receive the reply from the APNs server; the JVM will not do that for you.

When you send many notifications, the process of sending those notifications takes long enough that some (but I’m guessing not all) of the replies have time to come back. It may also be that you’re sending lots of notifications from some context where the JVM keeps running for a long time, like in a web application.

Here’s a very simple example:

public static void main(final String... args) {
    CompletableFuture.runAsync(() -> {
        System.out.println("Sleeping for 8 seconds");

        try {
            Thread.sleep(8_000);
        } catch (InterruptedException e) {
            System.err.println("Interrupted while sleeping");
        }

        System.out.println("Done sleeping!");
    });
}

This example will exit immediately without doing much of anything. It might print “Sleeping for 8 seconds,” but in almost all cases it will just exit without even doing that much. The problem is that we’ve started a process that will take a long time (8 seconds) to complete, but aren’t waiting for it to finish.

As an analogy, putting a letter in a mailbox is very quick, but it will still take a relatively long time for the letter to arrive at its destination and for a reply to come back. In this example, we’re putting the letter in the mailbox, then immediately giving up because we haven’t received a reply.

The same is true with Pushy; calling sendNotification is like putting a letter in the mail. Calling sendNotification is very quick, but if you want the reply, you must wait for it somehow.

I hope that helps!

0reactions
liuxu0703commented, Nov 2, 2020

Sorry for this late reply, been a little too busy about other things… In our case, the demo was started in a web server application, which will not quit until we shut it down. That is why we can receive the first reply when a second push was fired. Like the good author said, it is a little tricky to provide the demo since many private configurations and keys are involved. We will keep an eye on the issue, and if we can find a pattern, I will write the reproduce steps here. Thanks again for this marvelous lib and many thanks for your time spend on this issue.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Does not calling Future.get cause any issue? - Stack Overflow
The future will be garbage collected as long as no one is holding a reference to it. Obviously you could submit a Runnable...
Read more >
Future (Java Platform SE 7 ) - Oracle Help Center
A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its...
Read more >
1.1.6 (core) / 0.17.6 (libraries) - Dagster Docs
You can view the freshness status of each asset in Dagit, alert when assets are missing their targets using the @freshness_policy_sensor , and...
Read more >
kong/CHANGELOG.md at master - GitHub
The up_f part is invoked after the up part has been executed against the database for both Postgres and Cassandra. A new CLI...
Read more >
Changelog — aiohttp 3.8.3 documentation
The build fails loudly if aiohttp cannot be compiled with C Accelerators. Use AIOHTTP_NO_EXTENSIONS=1 to explicitly disable C Extensions complication and ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found