Skip to content
This repository was archived by the owner on Feb 7, 2020. It is now read-only.

Commit e139e24

Browse files
authored
Merge pull request #2 from ripienaar/1
(#1) add a shutdown event
2 parents 7a10c2a + c180449 commit e139e24

File tree

6 files changed

+177
-8
lines changed

6 files changed

+177
-8
lines changed

event.go

+1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ type Event interface {
66
String() string
77
Component() string
88
Type() Type
9+
SetIdentity(string)
910
}

lifecycle.go

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/json"
55
"errors"
66
"fmt"
7+
"sort"
78
"strings"
89

910
"github.com/tidwall/gjson"
@@ -22,6 +23,9 @@ const (
2223

2324
// Startup is an event components should publish when they start
2425
Startup Type = iota
26+
27+
// Shutdown is an event components should publish when they shutdown
28+
Shutdown
2529
)
2630

2731
var eventTypes = make(map[string]Type)
@@ -46,6 +50,8 @@ func EventTypeNames() []string {
4650
names = append(names, k)
4751
}
4852

53+
sort.Strings(names)
54+
4955
return names
5056
}
5157

events_test.go renamed to lifecycle_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ var _ = Describe("Events", func() {
4949

5050
Describe("EventTypeNames", func() {
5151
It("Should list all known types", func() {
52-
Expect(EventTypeNames()).To(Equal([]string{"startup"}))
52+
Expect(EventTypeNames()).To(Equal([]string{"shutdown", "startup"}))
5353
})
5454
})
5555

options.go

+2-7
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@ import (
77
// Option configures events
88
type Option func(e interface{}) error
99

10-
// IdentityEvent is an event that has an identity
11-
type IdentityEvent interface {
12-
SetIdentity(string)
13-
}
14-
1510
// VersionEvent is an event that has a version
1611
type VersionEvent interface {
1712
SetVersion(string)
@@ -53,9 +48,9 @@ func Version(version string) Option {
5348
// Identity sets the identity for events
5449
func Identity(identity string) Option {
5550
return func(e interface{}) error {
56-
event, ok := e.(IdentityEvent)
51+
event, ok := e.(Event)
5752
if !ok {
58-
return errors.New("cannot set component, event does not implement IdentityEvent")
53+
return errors.New("cannot set component, event does not implement Event")
5954
}
6055

6156
event.SetIdentity(identity)

shutdown.go

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package lifecycle
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
)
7+
8+
// ShutdownEvent is a choria:lifecycle:shutdown:1 event
9+
type ShutdownEvent struct {
10+
Protocol string `json:"protocol"`
11+
Identity string `json:"identity"`
12+
Comp string `json:"component"`
13+
Timestamp int64 `json:"timestamp"`
14+
}
15+
16+
func init() {
17+
eventTypes["shutdown"] = Shutdown
18+
19+
eventJSONParsers[Shutdown] = func(j []byte) (Event, error) {
20+
return newShutdownEventFromJSON(j)
21+
}
22+
23+
eventFactories[Shutdown] = func(opts ...Option) Event {
24+
return newShutdownEvent(opts...)
25+
}
26+
}
27+
28+
func newShutdownEvent(opts ...Option) *ShutdownEvent {
29+
event := &ShutdownEvent{
30+
Protocol: "choria:lifecycle:shutdown:1",
31+
Timestamp: timeStamp(),
32+
}
33+
34+
for _, o := range opts {
35+
o(event)
36+
}
37+
38+
return event
39+
}
40+
41+
func newShutdownEventFromJSON(j []byte) (*ShutdownEvent, error) {
42+
event := &ShutdownEvent{}
43+
err := json.Unmarshal(j, event)
44+
if err != nil {
45+
return nil, err
46+
}
47+
48+
if event.Protocol != "choria:lifecycle:shutdown:1" {
49+
return nil, fmt.Errorf("invalid protocol '%s'", event.Protocol)
50+
}
51+
52+
return event, nil
53+
}
54+
55+
// Component is the component that produced the event
56+
func (e *ShutdownEvent) Component() string {
57+
return e.Comp
58+
}
59+
60+
// SetComponent sets the component for the event
61+
func (e *ShutdownEvent) SetComponent(c string) {
62+
e.Comp = c
63+
}
64+
65+
// SetIdentity sets the identity for the event
66+
func (e *ShutdownEvent) SetIdentity(i string) {
67+
e.Identity = i
68+
}
69+
70+
// Target is where to publish the event to
71+
func (e *ShutdownEvent) Target() (string, error) {
72+
if e.Comp == "" {
73+
return "", fmt.Errorf("event is not complete, component has not been set")
74+
}
75+
76+
return fmt.Sprintf("choria.lifecycle.event.shutdown.%s", e.Comp), nil
77+
}
78+
79+
// String is text suitable to display on the console etc
80+
func (e *ShutdownEvent) String() string {
81+
return fmt.Sprintf("[shutdown] %s: %s", e.Identity, e.Component())
82+
}
83+
84+
// Type is the type of event
85+
func (e *ShutdownEvent) Type() Type {
86+
return Shutdown
87+
}

shutdown_test.go

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package lifecycle
2+
3+
import (
4+
. "github.com/onsi/ginkgo"
5+
. "github.com/onsi/gomega"
6+
)
7+
8+
var _ = Describe("ShutdownEvent", func() {
9+
Describe("newShutdownEvent", func() {
10+
It("Should create the event and set options", func() {
11+
event := newShutdownEvent(Component("ginkgo"))
12+
Expect(event.Component()).To(Equal("ginkgo"))
13+
})
14+
})
15+
16+
Describe("newShutdownEventFromJSON", func() {
17+
It("Should detect invalid protocols", func() {
18+
_, err := newShutdownEventFromJSON([]byte(`{"protocol":"x"}`))
19+
Expect(err).To(MatchError("invalid protocol 'x'"))
20+
})
21+
22+
It("Should parse valid events", func() {
23+
event, err := newShutdownEventFromJSON([]byte(`{"protocol":"choria:lifecycle:shutdown:1", "component":"ginkgo"}`))
24+
Expect(err).ToNot(HaveOccurred())
25+
Expect(event.Component()).To(Equal("ginkgo"))
26+
})
27+
})
28+
29+
Describe("Component", func() {
30+
It("Should return the right component", func() {
31+
e := &ShutdownEvent{Comp: "test"}
32+
Expect(e.Component()).To(Equal("test"))
33+
})
34+
})
35+
36+
Describe("SetComponent", func() {
37+
It("Should set the component", func() {
38+
e := &ShutdownEvent{}
39+
e.SetComponent("component")
40+
Expect(e.Comp).To(Equal("component"))
41+
})
42+
})
43+
44+
Describe("SetIdentity", func() {
45+
It("Should set the identity", func() {
46+
e := &ShutdownEvent{}
47+
e.SetIdentity("node.example")
48+
Expect(e.Identity).To(Equal("node.example"))
49+
})
50+
})
51+
52+
Describe("Target", func() {
53+
It("Should detect incomplete events", func() {
54+
e := &ShutdownEvent{}
55+
_, err := e.Target()
56+
Expect(err).To(MatchError("event is not complete, component has not been set"))
57+
})
58+
59+
It("Should return the right target", func() {
60+
e := newShutdownEvent(Component("ginkgo"))
61+
t, err := e.Target()
62+
Expect(err).ToNot(HaveOccurred())
63+
Expect(t).To(Equal("choria.lifecycle.event.shutdown.ginkgo"))
64+
})
65+
})
66+
67+
Describe("String", func() {
68+
It("Should return the right string", func() {
69+
e := newShutdownEvent(Component("ginkgo"), Identity("node.example"))
70+
Expect(e.String()).To(Equal("[shutdown] node.example: ginkgo"))
71+
})
72+
})
73+
74+
Describe("Type", func() {
75+
It("Should return the right Type", func() {
76+
e := &ShutdownEvent{}
77+
Expect(e.Type()).To(Equal(Shutdown))
78+
})
79+
})
80+
})

0 commit comments

Comments
 (0)