-
Notifications
You must be signed in to change notification settings - Fork 27
/
sync.go
85 lines (77 loc) · 2.61 KB
/
sync.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// Contains the sync status reporting.
package main
import (
"time"
"github.com/gophergala2016/etherapis/etherapis/Godeps/_workspace/src/gopkg.in/inconshreveable/log15.v2"
"github.com/gophergala2016/etherapis/etherapis/geth"
)
// monitorSync runs in an inifite loop, periodically checking if the attached
// node is synchronizing or not, and writing some log entries.
func monitorSync(api *geth.API) {
start := time.Now()
for {
// Wait a bit before checking the status, first is irrelevant anyway
time.Sleep(time.Second)
// Retrieve the sync status and go back to sleep if not syncing
status, err := api.Syncing()
if err != nil {
log15.Error("Failed to retrieve sync status", "error", err)
continue
}
if status == nil {
start = time.Now()
continue
}
// Yay, something's actually happening, display a log
if status.CurrentBlock > status.StartingBlock {
var (
totalBlocks = status.HighestBlock - status.StartingBlock
pulledBlocks = status.CurrentBlock - status.StartingBlock
estimate = time.Since(start) * time.Duration(totalBlocks) / time.Duration(pulledBlocks)
)
log15.Info("Synchronizing with the network...", "at", status.CurrentBlock, "total", status.HighestBlock, "eta", estimate)
}
}
}
// waitSync blocks execution until the chain is synchronized with the network,
// which usually entails waiting until syncing reports false, with the added
// criteria that we actually have a decently current block (< 3 mins).
func waitSync(freshness time.Duration, api *geth.API) {
notified := false
for {
// Wait until sync reports false
for {
// Fetch the sync status
status, err := api.Syncing()
if err != nil {
log15.Error("Failed to retrieve sync status", "error", err)
} else if status == nil {
break
}
// Sleep if syncing
time.Sleep(250 * time.Millisecond)
}
// We're supposedly in sync, double check the block timestamp
head, err := api.BlockNumber()
if err != nil {
log15.Error("Failed to retrieve head block number", "error", err)
break
}
mined, err := api.GetBlockTime(head)
if err != nil {
log15.Error("Failed to retrieve head block timestamp", "number", head, "error", err)
break
}
if time.Since(mined) <= freshness {
log15.Info("In sync with the network", "block", head, "freshness", time.Since(mined))
return
}
// Seems we're not in sync, wait a bit and retry
if !notified {
log15.Info("You seem out of sync, updating...", "freshness", time.Since(mined), "allowed", freshness)
log15.Warn("We're sorry this isn't faster, test network's feisty :)")
notified = true
}
time.Sleep(250 * time.Millisecond)
}
}