instacart / truetime-android

Android NTP time library. Get the true current time impervious to device clock time changes
https://tech.instacart.com/truetime/
Apache License 2.0
1.42k stars 195 forks source link

Time is not returned until all requests have been resolved #109

Open MarkVillacampa opened 5 years ago

MarkVillacampa commented 5 years ago

If the NTP server I'm using resolves to 4 IPs, then TrueTime will make 4 x 5 = 20 requests. If only one of those requests times out (30 seconds by default), even if all 19 other requests are successful, TrueTime will not calculate a time until after that request succeeds.

I am not sure if this is included in the NTP spec or it's a design decision in the TrueTime library, but would it make sense to include an option to accept a threshold of successful requests after which the time can be calculated, discarding the few failed requests? Say, if up to 10% of requests fail, still pick the best one of the ones that succeeded.

Example of one failed request holding back time calculation for 30 seconds:

2019-01-18 00:05:52.733 30803-31157/com.myapp I/MYAPP: ---- Running TrueTime init now
2019-01-18 00:05:52.733 30803-31134/com.myapp I/MYAPP: ---- TrueTime Syncer called
2019-01-18 00:05:52.772 30803-31157/com.myapp D/TrueTimeRx: ---- resolving ntpHost : time.google.com
2019-01-18 00:05:52.789 30803-31158/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.4
2019-01-18 00:05:52.789 30803-31160/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.4
2019-01-18 00:05:52.792 30803-31161/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.4
2019-01-18 00:05:52.796 30803-31164/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.0
2019-01-18 00:05:52.799 30803-31165/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.0
2019-01-18 00:05:52.804 30803-31166/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.0
2019-01-18 00:05:52.804 30803-31163/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.4
2019-01-18 00:05:52.805 30803-31162/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.4
2019-01-18 00:05:52.807 30803-31167/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.0
2019-01-18 00:05:52.809 30803-31168/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.0
2019-01-18 00:05:52.813 30803-31169/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.8
2019-01-18 00:05:52.816 30803-31170/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.8
2019-01-18 00:05:52.818 30803-31171/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.8
2019-01-18 00:05:52.820 30803-31172/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.8
2019-01-18 00:05:52.822 30803-31173/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.8
2019-01-18 00:05:52.823 30803-31174/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.12
2019-01-18 00:05:52.824 30803-31175/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.12
2019-01-18 00:05:52.825 30803-31176/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.12
2019-01-18 00:05:52.826 30803-31177/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.12
2019-01-18 00:05:52.827 30803-31178/com.myapp D/TrueTimeRx: ---- requestTime from: 216.239.35.12
2019-01-18 00:06:22.821 30803-31158/com.myapp D/SntpClient: ---- SNTP request failed for 216.239.35.4
2019-01-18 00:06:22.833 30803-31158/com.myapp E/TrueTimeRx: ---- Error requesting time
    java.net.SocketTimeoutException: Receive timed out
        at java.net.PlainDatagramSocketImpl.receive0(Native Method)
        at java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:147)
        at java.net.DatagramSocket.receive(DatagramSocket.java:811)
        at com.instacart.library.truetime.SntpClient.requestTime(SntpClient.java:123)
        at com.instacart.library.truetime.TrueTime.requestTime(TrueTime.java:133)
        at com.instacart.library.truetime.TrueTimeRx$4$1$2.subscribe(TrueTimeRx.java:211)
        at io.reactivex.internal.operators.flowable.FlowableCreate.subscribeActual(FlowableCreate.java:72)
        at io.reactivex.Flowable.subscribe(Flowable.java:14409)
        at io.reactivex.Flowable.subscribe(Flowable.java:14356)
        at io.reactivex.internal.operators.flowable.FlowableSubscribeOn$SubscribeOnSubscriber.run(FlowableSubscribeOn.java:82)
        at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
        at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
        at java.lang.Thread.run(Thread.java:762)
2019-01-18 00:06:22.882 30803-31160/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.4
2019-01-18 00:06:22.943 30803-31161/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.4
2019-01-18 00:06:22.972 30803-31164/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.0
2019-01-18 00:06:23.003 30803-31165/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.0
2019-01-18 00:06:23.031 30803-31166/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.0
2019-01-18 00:06:23.092 30803-31163/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.4
2019-01-18 00:06:23.159 30803-31162/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.4
2019-01-18 00:06:23.187 30803-31167/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.0
2019-01-18 00:06:23.215 30803-31168/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.0
2019-01-18 00:06:23.243 30803-31169/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.8
2019-01-18 00:06:23.272 30803-31170/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.8
2019-01-18 00:06:23.303 30803-31171/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.8
2019-01-18 00:06:23.336 30803-31172/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.8
2019-01-18 00:06:23.379 30803-31173/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.8
2019-01-18 00:06:23.414 30803-31174/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.12
2019-01-18 00:06:23.449 30803-31175/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.12
2019-01-18 00:06:23.489 30803-31176/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.12
2019-01-18 00:06:23.524 30803-31177/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.12
2019-01-18 00:06:23.560 30803-31178/com.myapp I/SntpClient: ---- SNTP successful response from 216.239.35.12
jemshit commented 5 years ago

From my observation, even if it does not propagate result to onSuccess yet, you can call TrueTimeRx.now() to get intermediate best result.

safa007 commented 5 years ago

I'd also like to request the ability to discard failed requests. For the purposes of what I need TrueTimeRx for, I just need the first successful request that comes in.