/
environment.go
119 lines (99 loc) · 3.38 KB
/
environment.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
package latvis
import (
"log"
"net/http"
"net/url"
)
// ======================================
// ========== ENVIRONMENT API ===========
// ======================================
// Environment encapsulates the dependencies for a latvis server.
//
// Applications should prefer to access system level services (data storage, network
// requests, etc.) via the Environment rather than directly in order to support
// both unit-testing, and also portability (e.g. to the Google Appengine sandbox).
type Environment struct {
blobStore BlobStore
taskQueue UrlTaskQueue
mockRenderEngine RenderEngineInterface
logger Logger
httpTransport http.RoundTripper
}
func (env *Environment) Errorf(format string, args ...interface{}) {
if env.logger != nil {
env.logger.Errorf(format, args)
}
}
func (env *Environment) RenderEngineForRequest(request *http.Request) RenderEngineInterface {
if env.mockRenderEngine != nil {
return env.mockRenderEngine
}
return NewRenderEngine(env.blobStore, env.httpTransport)
}
// Use this instead of &Environment{...} directly to get compile-timer
// errors when new dependencies are introduced.
func NewEnvironment(blobStore BlobStore,
taskQueue UrlTaskQueue,
logger Logger,
httpTransport http.RoundTripper) *Environment {
return &Environment{
blobStore: blobStore,
taskQueue: taskQueue,
logger: logger,
httpTransport: httpTransport,
}
}
// It's assumed that an Environment will be request-specific (it is for Appengine),
// an EnvironmentFactory will create a new Environment for any given request.
type EnvironmentFactory interface {
ForRequest(request *http.Request) *Environment
}
// ======================================
// ========= SYSTEM/SERVICE APIS ========
// ======================================
type Logger interface {
Errorf(format string, args ...interface{})
}
// UrlTaskQueue
//
// Maintains, and executes a queue of tasks. The tasks are represented as a
// base URL, plus query params.
//
// Although this removes a dependency on appengine-specific *code*, this is a
// somewhat appengine-specific *concept*. Of course, there's no reason any
// server would choose to implement tasks this way, but I'm not sure it would
// be the first choice. Anyway, for now we'll live with it.
type UrlTaskQueue interface {
Enqueue(url string, params *url.Values) error
}
// ======================================
// ======= DEFAULT IMPLEMENTATIONS ======
// ======================================
// SyncUrlTaskQueue
//
// This hasn't been implemented yet, but the idea is that it would just call
// the URL over HTTP direcly, and block waiting for a response.
type SyncUrlTaskQueue struct {
baseUrl string
}
func (q *SyncUrlTaskQueue) Enqueue(url string, params *url.Values) error {
// u := url.Parse(baseUrl + url + params.Encode())
// var req http.Request
// req.Method = "GET"
// req.header = http.Header{}
// req.URL = u
panic("Not Implemented")
}
type DefaultLogger struct{}
func (l DefaultLogger) Errorf(format string, args ...interface{}) {
log.Printf(format, args)
}
type StaticEnvironmentFactory struct {
staticEnvironment *Environment
}
func NewStaticEnvironmentFactory(staticEnvironment *Environment) EnvironmentFactory {
return &StaticEnvironmentFactory{staticEnvironment: staticEnvironment}
}
func (cf *StaticEnvironmentFactory) ForRequest(request *http.Request) *Environment {
return cf.staticEnvironment
}