d1f1fe0752
After discussion with others and thinking about the notification channel some more, we've decided to leave it up to the caller to quickly handle notifications. While it is true that notification should be handled quickly to not block the chain processing code unnecessarily, launching a goroutine in chain means the notifications are no longer necessarily in order. Also, if the caller is not properly handling the notifications, the goroutines end up sicking around forever. By leaving it up to the caller to quickly handle the notification or launch a goroutine as necessary for the caller, it provides the flexibility to ensure proper notification ordering as well as control over other things such as how to handle backpressure.
77 lines
2.5 KiB
Go
77 lines
2.5 KiB
Go
// Copyright (c) 2013 Conformal Systems LLC.
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package btcchain
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
// NotificationType represents the type of a notification message.
|
|
type NotificationType int
|
|
|
|
// Constants for the type of a notification message.
|
|
const (
|
|
// NTOrphanBlock indicates an orphan block was processed and the
|
|
// associated block hash should be passed to the GetOrphanRoot function
|
|
// to find the root of all known orphans which should then be used to
|
|
// request the missing blocks.
|
|
NTOrphanBlock NotificationType = iota
|
|
|
|
// NTBlockAccepted indicates the associated block was accepted into
|
|
// the block chain. Note that this does not necessarily mean it was
|
|
// added to the main chain. For that, use NTBlockConnected.
|
|
NTBlockAccepted
|
|
|
|
// NTBlockConnected indicates the associated block was connected to the
|
|
// main chain.
|
|
NTBlockConnected
|
|
|
|
// NTBlockDisconnected indicates the associated block was disconnected
|
|
// from the main chain.
|
|
NTBlockDisconnected
|
|
)
|
|
|
|
// notificationTypeStrings is a map of notification types back to their constant
|
|
// names for pretty printing.
|
|
var notificationTypeStrings = map[NotificationType]string{
|
|
NTOrphanBlock: "NTOrphanBlock",
|
|
NTBlockAccepted: "NTBlockAccepted",
|
|
NTBlockConnected: "NTBlockConnected",
|
|
NTBlockDisconnected: "NTBlockDisconnected",
|
|
}
|
|
|
|
// String returns the NotificationType in human-readable form.
|
|
func (n NotificationType) String() string {
|
|
if s, ok := notificationTypeStrings[n]; ok {
|
|
return s
|
|
}
|
|
return fmt.Sprintf("Unknown Notification Type (%d)", int(n))
|
|
}
|
|
|
|
// Notification defines an asynchronous notification that is sent to the caller
|
|
// over the notification channel provided during the call to New and consists
|
|
// of a notification type as well as associated data that depends on the type as
|
|
// follows:
|
|
// - NTOrphanBlock: *btcwire.ShaHash
|
|
// - NTBlockAccepted: *btcutil.Block
|
|
// - NTBlockConnected: *btcutil.Block
|
|
// - NTBlockDisconnected: *btcutil.Block
|
|
type Notification struct {
|
|
Type NotificationType
|
|
Data interface{}
|
|
}
|
|
|
|
// sendNotification sends a notification with the passed type and data if the
|
|
// caller requested notifications by providing a channel in the call to New.
|
|
func (b *BlockChain) sendNotification(typ NotificationType, data interface{}) {
|
|
// Ignore it if the caller didn't request notifications.
|
|
if b.notifications == nil {
|
|
return
|
|
}
|
|
|
|
// Generate and send the notification.
|
|
n := Notification{Type: typ, Data: data}
|
|
b.notifications <- &n
|
|
}
|