refactor EventType construction.

This commit is contained in:
Raúl Kripalani 2020-07-17 18:35:15 +01:00
parent 695f6cfe45
commit bef7d64e66
4 changed files with 89 additions and 31 deletions

View File

@ -21,7 +21,7 @@ var log = logging.Logger("journal")
// fsJournal is a basic journal backed by files on a filesystem.
type fsJournal struct {
disabledTracker
*eventTypeFactory
dir string
sizeLimit int64
@ -44,11 +44,11 @@ func OpenFSJournal(lr repo.LockedRepo, lc fx.Lifecycle, disabled []EventType) (J
}
f := &fsJournal{
disabledTracker: newDisabledTracker(disabled),
dir: dir,
sizeLimit: 1 << 30,
incoming: make(chan *Entry, 32),
closing: make(chan struct{}),
eventTypeFactory: newEventTypeFactory(disabled),
dir: dir,
sizeLimit: 1 << 30,
incoming: make(chan *Entry, 32),
closing: make(chan struct{}),
}
if err := f.rollJournalFile(); err != nil {

View File

@ -21,7 +21,7 @@ type (
)
type MemJournal struct {
disabledTracker
*eventTypeFactory
entries []*Entry
index map[string]map[string][]*Entry
@ -52,7 +52,7 @@ func (o *observer) dispatch(entry *Entry) {
func NewMemoryJournal(lc fx.Lifecycle, disabled []EventType) *MemJournal {
m := &MemJournal{
disabledTracker: newDisabledTracker(disabled),
eventTypeFactory: newEventTypeFactory(disabled),
index: make(map[string]map[string][]*Entry, 16),
observers: make([]observer, 0, 16),
@ -72,6 +72,11 @@ func NewMemoryJournal(lc fx.Lifecycle, disabled []EventType) *MemJournal {
}
func (m *MemJournal) AddEntry(evtType EventType, obj interface{}) {
if !evtType.enabled || !evtType.safe {
// tried to record a disabled event type, or used an invalid EventType.
return
}
entry := &Entry{
EventType: evtType,
Timestamp: build.Clock.Now(),
@ -109,8 +114,12 @@ func (m *MemJournal) Clear() {
func (m *MemJournal) Observe(ctx context.Context, replay bool, include ...EventType) <-chan *Entry {
var acc map[EventType]struct{}
if include != nil {
acc = make(map[EventType]struct{}, 16)
acc = make(map[EventType]struct{}, len(include))
for _, et := range include {
if !et.enabled {
// skip over disabled event type.
continue
}
acc[et] = struct{}{}
}
}

View File

@ -111,8 +111,11 @@ func TestMemJournal_Observe(t *testing.T) {
require.Eventually(t, func() bool { return len(journal.Entries()) == 100 }, 1*time.Second, 100*time.Millisecond)
o1 := journal.Observe(context.TODO(), false, EventType{"spaceship", "wheezing-1"})
o2 := journal.Observe(context.TODO(), true, EventType{"spaceship", "wheezing-1"}, EventType{"spaceship", "wheezing-2"})
et1 := journal.RegisterEventType("spaceship", "wheezing-1")
et2 := journal.RegisterEventType("spaceship", "wheezing-2")
o1 := journal.Observe(context.TODO(), false, et1)
o2 := journal.Observe(context.TODO(), true, et1, et2)
o3 := journal.Observe(context.TODO(), true)
time.Sleep(1 * time.Second)
@ -160,13 +163,15 @@ func TestMemJournal_ObserverCancellation(t *testing.T) {
require.Len(t, o1, 100) // has not moved.
require.Len(t, o2, 150) // should have 100 old entries + 50 new entries
}
func addEntries(journal *MemJournal, count int) {
for i := 0; i < count; i++ {
eventIdx := i % 10
journal.AddEntry(EventType{"spaceship", fmt.Sprintf("wheezing-%d", eventIdx)}, HeadChangeEvt{
// RegisterEventType is not _really_ intended to be used this way (on every write).
et := journal.RegisterEventType("spaceship", fmt.Sprintf("wheezing-%d", eventIdx))
journal.AddEntry(et, HeadChangeEvt{
From: types.TipSetKey{},
FromHeight: abi.ChainEpoch(i),
To: types.TipSetKey{},

View File

@ -1,11 +1,32 @@
package journal
import "time"
import (
"sync"
"time"
)
// EventType represents the signature of an event.
type EventType struct {
System string
Event string
// enabled stores whether this event type is enabled.
enabled bool
// safe is a sentinel marker that's set to true if this EventType was
// constructed correctly (via Journal#RegisterEventType).
safe bool
}
// Enabled returns whether this event type is enabled in the journaling
// subsystem. Users are advised to check this before actually attempting to
// add a journal entry, as it helps bypass object construction for events that
// would be discarded anyway.
//
// All event types are enabled by default, and specific event types can only
// be disabled at Journal construction time.
func (et EventType) Enabled() bool {
return et.enabled
}
// Journal represents an audit trail of system actions.
@ -17,12 +38,11 @@ type EventType struct {
// For cleanliness and type safety, we recommend to use typed events. See the
// *Evt struct types in this package for more info.
type Journal interface {
// IsEnabled allows components to check if a given event type is enabled.
// All event types are enabled by default, and specific event types can only
// be disabled at construction type. Components are advised to check if the
// journal event types they record are enabled as soon as possible, and hold
// on to the answer all throughout the lifetime of the process.
IsEnabled(evtType EventType) bool
// RegisterEventType introduces a new event type to this journal, and
// returns an EventType token that components can later use to check whether
// journalling for that type is enabled/suppressed, and to tag journal
// entries appropriately.
RegisterEventType(system, event string) EventType
// AddEntry adds an entry to this journal. See godocs on the Journal type
// for more info.
@ -42,19 +62,43 @@ type Entry struct {
Data interface{}
}
// disabledTracker is an embeddable mixin that takes care of tracking disabled
// event types.
type disabledTracker map[EventType]struct{}
// eventTypeFactory is an embeddable mixin that takes care of tracking disabled
// event types, and returning initialized/safe EventTypes when requested.
type eventTypeFactory struct {
sync.Mutex
func newDisabledTracker(disabled []EventType) disabledTracker {
dis := make(map[EventType]struct{}, len(disabled))
for _, et := range disabled {
dis[et] = struct{}{}
m map[string]EventType
}
func newEventTypeFactory(disabled []EventType) *eventTypeFactory {
ret := &eventTypeFactory{
m: make(map[string]EventType, len(disabled)+32), // + extra capacity.
}
return dis
for _, et := range disabled {
et.enabled, et.safe = false, true
ret.m[et.System+":"+et.Event] = et
}
return ret
}
func (d disabledTracker) IsEnabled(evtType EventType) bool {
_, ok := d[evtType]
return !ok
func (d *eventTypeFactory) RegisterEventType(system, event string) EventType {
d.Lock()
defer d.Unlock()
key := system + ":" + event
if et, ok := d.m[key]; ok {
return et
}
et := EventType{
System: system,
Event: event,
enabled: true,
safe: true,
}
d.m[key] = et
return et
}