-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbackend.go
121 lines (93 loc) · 3.2 KB
/
backend.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
package scrimplb
import (
"bytes"
"compress/gzip"
"encoding/json"
"errors"
"fmt"
)
// BackendConfig describes configuration for backend instances
type BackendConfig struct {
Applications []JSONApplication `json:"applications"`
ApplicationConfigDir string `json:"application-config-dir"`
}
func initialiseBackendConfig(config *ScrimpConfig) error {
if config.BackendConfig == nil {
return errors.New(`missing backend config for '"lb": false' in config file. creating a backend with no applications is pointless`)
}
if config.BackendConfig.ApplicationConfigDir != "" {
extraApplications, err := configDirWalker(config.BackendConfig.ApplicationConfigDir)
if err != nil {
return err
}
config.BackendConfig.Applications = append(config.BackendConfig.Applications, extraApplications...)
}
if len(config.BackendConfig.Applications) == 0 {
return errors.New(`no applications given in config file or loaded from a config dir. creating a backend with no applications is pointless`)
}
for _, app := range config.BackendConfig.Applications {
if app.ListenPort == "80" {
return errors.New("invalid listen port '80' for application; only a redirect listener works on port 80")
}
if len(app.Domains) == 0 {
return errors.New("applications must have at least one domain")
}
// TODO: more validation
}
return nil
}
// BackendMetadata is returned by node metadata in the cluster, and describes
// supported applications on the backend.
type BackendMetadata struct {
Type string `json:"type"`
Applications []JSONApplication `json:"applications"`
}
// BackendDelegate listens for messages from other cluster members requesting
// details about a backend.
type BackendDelegate struct {
metadata []byte
}
// NewBackendDelegate creates a BackendDelegate from a channel which receives work tasks
func NewBackendDelegate(config *BackendConfig) (*BackendDelegate, error) {
backendMetadata := BackendMetadata{
"backend",
config.Applications,
}
rawMetadata, err := json.Marshal(backendMetadata)
if err != nil {
return nil, err
}
var buf bytes.Buffer
gzipWriter := gzip.NewWriter(&buf)
_, err = gzipWriter.Write(rawMetadata)
if err != nil {
return nil, fmt.Errorf("couldn't gzip application metadata: %w", err)
}
err = gzipWriter.Close()
if err != nil {
return nil, fmt.Errorf("couldn't close gzip metadata writer: %w", err)
}
return &BackendDelegate{
buf.Bytes(),
}, nil
}
// NodeMeta returns metadata about this backend, including a list of supported applications
func (b *BackendDelegate) NodeMeta(limit int) []byte {
return b.metadata
}
// NotifyMsg receives messages from other cluster members. If the message was
// intended for a backend, it is processed and a reply is scheduled if needed.
func (b *BackendDelegate) NotifyMsg(msg []byte) {
fmt.Printf("%v\n", string(msg))
}
// GetBroadcasts is ingored for BackendDelegate
func (b *BackendDelegate) GetBroadcasts(overhead int, limit int) [][]byte {
return nil
}
// LocalState is ignored for a BackendDelegate
func (b *BackendDelegate) LocalState(join bool) []byte {
return nil
}
// MergeRemoteState is ignored for BackendDelegate
func (b *BackendDelegate) MergeRemoteState(buf []byte, join bool) {
}