forked from nytimes/gizmo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
doc.go
187 lines (134 loc) · 6.67 KB
/
doc.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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
Package gizmo is a toolkit that provides packages to put together server and pubsub daemons with the following features:
* standardized configuration and logging
* health check endpoints with configurable strategies
* configuration for managing pprof endpoints and log levels
* structured logging containing basic request information
* useful metrics for endpoints
* graceful shutdowns
* basic interfaces to define our expectations and vocabulary
The `config` package
This package contains a handful of structs meant for managing common configuration options and credentials. There are currently configs for:
* MySQL
* MongoDB
* Oracle
* AWS (SNS, SQS, S3, DynamoDB)
* Kafka
* Gorilla's `securecookie`
* Gizmo Servers
The package also has a generic `Config` type that contains all of the above types. It's meant to be a 'catch all' struct that most applications should be able to use.
`config` also contains functions to load these config structs from JSON files, JSON blobs in Consul k/v or environment variables.
The `server` package
This package is the bulk of the toolkit and relies on `config` for any managing `Server` implementations. A server must implement the following interface:
// Server is the basic interface that defines what expect from any server.
type Server interface {
Register(Service) error
Start() error
Stop() error
}
The package offers 2 server implementations:
`SimpleServer`, which is capable of handling basic HTTP and JSON requests via 3 of the available `Service` implementations: `SimpleService`, `JSONService`, and `MixedService`. A service and these implenetations will be defined below.
`RPCServer`, which is capable of serving a gRPC server on one port and JSON endpoints on another. This kind of server can only handle the `RPCService` implementation.
The `Service` interface is minimal to allow for maximum flexibility:
type Service interface {
Prefix() string
// Middleware provides a hook for service-wide middleware
Middleware(http.Handler) http.Handler
}
The 3 service types that are accepted and hostable on the `SimpleServer`:
type SimpleService interface {
Service
// router - method - func
Endpoints() map[string]map[string]http.HandlerFunc
}
type JSONService interface {
Service
// router - method - func
JSONEndpoints() map[string]map[string]JSONEndpoint
// JSONMiddleware provides a hook for service-wide middleware around JSONEndpoints.
JSONMiddleware(JSONEndpoint) JSONEndpoint
}
type MixedService interface {
Service
// route - method - func
Endpoints() map[string]map[string]http.HandlerFunc
// route - method - func
JSONEndpoints() map[string]map[string]JSONEndpoint
// JSONMiddleware provides a hook for service-wide middleware around JSONEndpoints.
JSONMiddleware(JSONEndpoint) JSONEndpoint
}
Where a `JSONEndpoint` is defined as:
type JSONEndpoint func(*http.Request) (int, interface{}, error)
Also, the one service type that works with an `RPCServer`:
type RPCService interface {
Service
Service() (grpc.ServiceDesc, interface{})
// route - method - func
JSONEndpoints() map[string]map[string]JSONEndpoint
// JSONMiddleware provides a hook for service-wide middleware around JSONEndpoints.
JSONMiddlware(JSONEndpoint) JSONEndpoint
}
The `Middleware(..)` functions offer each service a 'hook' to wrap each of its endpoints. This may be handy for adding additional headers or context to the request. This is also the point where other, third-party middleware could be easily be plugged in (ie. oauth, tracing, metrics, logging, etc.)
The `pubsub` package
This package contains two generic interfaces for publishing data to queues and subscribing and consuming data from those queues.
// Publisher is a generic interface to encapsulate how we want our publishers
// to behave. Until we find reason to change, we're forcing all publishers
// to emit protobufs.
type Publisher interface {
// Publish will publish a message.
Publish(string, proto.Message) error
// Publish will publish a []byte message.
PublishRaw(string, []byte) error
}
// Subscriber is a generic interface to encapsulate how we want our subscribers
// to behave. For now the system will auto stop if it encounters any errors. If
// a user encounters a closed channel, they should check the Err() method to see
// what happened.
type Subscriber interface {
// Start will return a channel of raw messages
Start() <-chan SubscriberMessage
// Err will contain any errors returned from the consumer connection.
Err() error
// Stop will initiate a graceful shutdown of the subscriber connection
Stop() error
}
Where a `SubscriberMessage` is an interface that gives implementations a hook for acknowledging/delete messages. Take a look at the docs for each implementation in `pubsub` to see how they behave.
There are currently 2 implementations of each type of `pubsub` interfaces:
For pubsub via Amazon's SNS/SQS, you can use the `SNSPublisher` and the `SQSSubscriber`.
For pubsub via Kafka topics, you can use the `KakfaPublisher` and the `KafkaSubscriber`.
The `pubsub/pubsubtest` package
This package contains 'test' implementations of the `pubsub.Publisher` and `pubsub.Subscriber` interfaces that will allow developers to easily mock out and test their `pubsub` implementations:
type TestPublisher struct {
// Published will contain a list of all messages that have been published.
Published []TestPublishMsg
// GivenError will be returned by the TestPublisher on publish.
// Good for testing error scenarios.
GivenError error
// FoundError will contain any errors encountered while marshalling
// the protobuf struct.
FoundError error
}
type TestSubscriber struct {
// ProtoMessages will be marshalled into []byte used to mock out
// a feed if it is populated.
ProtoMessages []proto.Message
// JSONMEssages will be marshalled into []byte and used to mock out
// a feed if it is populated.
JSONMessages []interface{}
// GivenErrError will be returned by the TestSubscriber on Err().
// Good for testing error scenarios.
GivenErrError error
// GivenStopError will be returned by the TestSubscriber on Stop().
// Good for testing error scenarios.
GivenStopError error
// FoundError will contain any errors encountered while marshalling
// the JSON and protobuf struct.
FoundError error
}
The `web` package
This package contains a handful of very useful functions for parsing types from request queries and payloads.
Examples
For examples of how to use the gizmo `server` and `pubsub` packages, take a look at the 'examples' subdirectory.
The Gizmo logo was based on the Go mascot designed by Renée French and copyrighted under the Creative Commons Attribution 3.0 license.
*/
package gizmo