Skip to content

Commit 9dfb8fb

Browse files
authored
refactor: yomo run zipper from a config file (#496)
# Description 1. Support Zipper launch from a config file. 2. Remove the `-a -m` flag from `yomo serve`, as all configurations are now covered by the configuration file. 3. If you want to develop a Zipper, use `yomo.NewZipper()`. If you want to run a Zipper from a configuration, use `yomo.RunZipper()`.
1 parent 34261b5 commit 9dfb8fb

61 files changed

Lines changed: 452 additions & 783 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cli/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ cd example/stream-fn-db && yomo build && ./sl.yomo
7474

7575
### 4. YoMo-Zipper
7676

77-
#### Configure YoMo-Zipper `workflow.yaml`
77+
#### Configure YoMo-Zipper `config.yaml`
7878

7979
```yaml
8080
name: Service
@@ -88,7 +88,7 @@ functions:
8888
#### Run
8989
9090
```sh
91-
yomo serve --config workflow.yaml
91+
yomo serve --config config.yaml
9292
```
9393

9494
## Example

cli/README_CN.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ cd example/stream-fn-db && yomo build && ./sl.yomo
6363
```
6464

6565
### 4. YoMo-Zipper 应用编排
66-
#### 编写工作流配置文件 `workflow.yaml`
66+
#### 编写工作流配置文件 `config.yaml`
6767

6868
```yaml
6969
name: Service
@@ -76,7 +76,7 @@ functions:
7676
#### 运行 YoMo-Zipper 应用程序
7777
7878
```shell
79-
yomo serve --config workflow.yaml
79+
yomo serve --config config.yaml
8080
```
8181

8282
## 示例

cli/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func init() {
9696
rootCmd.AddCommand(runCmd)
9797

9898
runCmd.Flags().StringVarP(&url, "zipper", "z", "localhost:9000", "YoMo-Zipper endpoint addr")
99-
runCmd.Flags().StringVarP(&opts.Name, "name", "n", "", "yomo stream function name. It should match the specific service name in YoMo-Zipper config (workflow.yaml)")
99+
runCmd.Flags().StringVarP(&opts.Name, "name", "n", "", "yomo stream function name. It should match the specific service name in YoMo-Zipper config (config.yaml)")
100100
runCmd.Flags().StringVarP(&opts.ModFile, "modfile", "m", "", "custom go.mod")
101101
runCmd.Flags().StringVarP(&opts.Credential, "credential", "d", "", "client credential payload, eg: `token:dBbBiRE7`")
102102
runCmd.Flags().StringVarP(&opts.Runtime, "runtime", "r", "", "serverless runtime type")

cli/serve.go

Lines changed: 5 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -16,59 +16,28 @@ limitations under the License.
1616
package cli
1717

1818
import (
19+
"context"
1920
"os"
20-
"strings"
2121

2222
"github.com/spf13/cobra"
23-
"github.com/spf13/viper"
2423
"github.com/yomorun/yomo"
2524
"github.com/yomorun/yomo/pkg/log"
2625
)
2726

28-
var meshConfURL string
29-
var v *viper.Viper
30-
3127
// serveCmd represents the serve command
3228
var serveCmd = &cobra.Command{
3329
Use: "serve",
3430
Short: "Run a YoMo-Zipper",
3531
Long: "Run a YoMo-Zipper",
3632
Run: func(cmd *cobra.Command, args []string) {
3733
if config == "" {
38-
log.FailureStatusEvent(os.Stdout, "Please input the file name of workflow config")
39-
return
40-
}
41-
// printYoMoServerConf(conf)
42-
43-
// endpoint := fmt.Sprintf("%s:%d", conf.Host, conf.Port)
44-
45-
zipper, err := yomo.NewZipper(config)
46-
if err != nil {
47-
log.FailureStatusEvent(os.Stdout, err.Error())
48-
return
49-
}
50-
// auth
51-
auth := v.GetString("auth")
52-
if len(auth) > 0 {
53-
idx := strings.Index(auth, ":")
54-
if idx != -1 {
55-
authName := auth[:idx]
56-
idx++
57-
args := auth[idx:]
58-
authArgs := strings.Split(args, ",")
59-
// log.InfoStatusEvent(os.Stdout, "authName=%s, authArgs=%s, idx=%d", authName, authArgs, idx)
60-
zipper.InitOptions(yomo.WithAuth(authName, authArgs...))
61-
}
62-
}
63-
// mesh
64-
err = zipper.ConfigMesh(meshConfURL)
65-
if err != nil {
66-
log.FailureStatusEvent(os.Stdout, err.Error())
34+
log.FailureStatusEvent(os.Stdout, "Please input the file name of config")
6735
return
6836
}
6937

7038
log.InfoStatusEvent(os.Stdout, "Running YoMo-Zipper...")
71-
err = zipper.ListenAndServe()
39+
40+
err := yomo.RunZipper(context.Background(), config)
7241
if err != nil {
7342
log.FailureStatusEvent(os.Stdout, err.Error())
7443
return
@@ -79,13 +48,5 @@ var serveCmd = &cobra.Command{
7948
func init() {
8049
rootCmd.AddCommand(serveCmd)
8150

82-
serveCmd.Flags().StringVarP(&config, "config", "c", "", "Workflow config file")
83-
serveCmd.Flags().StringVarP(&meshConfURL, "mesh-config", "m", "", "The URL of mesh config")
84-
// auth string
85-
serveCmd.Flags().StringP("auth", "a", "", "authentication name and arguments, eg: `token:yomo`")
86-
v = viper.New()
87-
v.AutomaticEnv()
88-
v.SetEnvPrefix("YOMO")
89-
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
90-
v.BindPFlag("auth", serveCmd.Flags().Lookup("auth"))
51+
serveCmd.Flags().StringVarP(&config, "config", "c", "", "config file")
9152
}

core/client.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,16 @@ func (c *Client) SetErrorHandler(fn func(err error)) {
320320
c.logger.Debug("the error handler has been set")
321321
}
322322

323-
// ClientID return the client ID
324-
func (c *Client) ClientID() string {
325-
return c.clientID
323+
// ClientID returns the ID of client.
324+
func (c *Client) ClientID() string { return c.clientID }
325+
326+
// Name returns the name of client.
327+
func (c *Client) Name() string { return c.name }
328+
329+
// FrameWriterConnection represents a frame writer that can connect to an addr.
330+
type FrameWriterConnection interface {
331+
frame.Writer
332+
Name() string
333+
Close() error
334+
Connect(context.Context, string) error
326335
}

core/client_test.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,21 @@ func TestFrameRoundTrip(t *testing.T) {
4242
)
4343

4444
server := NewServer("zipper",
45-
WithAddr(testaddr),
4645
WithAuth("token", "auth-token"),
4746
WithServerQuicConfig(DefalutQuicConfig),
4847
WithServerTLSConfig(nil),
4948
WithServerLogger(discardingLogger),
5049
)
5150
server.ConfigMetadataDecoder(metadata.DefaultDecoder())
52-
server.ConfigRouter(router.Default([]config.App{{Name: "sfn-1"}, {Name: "close-early-sfn"}}))
51+
server.ConfigRouter(router.Default([]config.Function{{Name: "sfn-1"}, {Name: "close-early-sfn"}}))
5352

5453
// test server hooks
5554
ht := &hookTester{t}
5655
server.SetStartHandlers(ht.startHandler)
5756
server.SetBeforeHandlers(ht.beforeHandler)
5857
server.SetAfterHandlers(ht.afterHandler)
5958

60-
recorder := newFrameWriterRecorder()
59+
recorder := newFrameWriterRecorder("mockClient")
6160
server.AddDownstreamServer("mockAddr", recorder)
6261

6362
go func() {
@@ -189,14 +188,19 @@ func createTestStreamFunction(name string, obversedTag frame.Tag) *Client {
189188

190189
// frameWriterRecorder frames be writen.
191190
type frameWriterRecorder struct {
192-
mu sync.Mutex
193-
buf *bytes.Buffer
191+
name string
192+
mu sync.Mutex
193+
buf *bytes.Buffer
194194
}
195195

196-
func newFrameWriterRecorder() *frameWriterRecorder {
197-
return &frameWriterRecorder{buf: bytes.NewBuffer([]byte{})}
196+
func newFrameWriterRecorder(name string) *frameWriterRecorder {
197+
return &frameWriterRecorder{name: name, buf: bytes.NewBuffer([]byte{})}
198198
}
199199

200+
func (w *frameWriterRecorder) Name() string { return w.name }
201+
func (w *frameWriterRecorder) Close() error { return nil }
202+
func (w *frameWriterRecorder) Connect(_ context.Context, _ string) error { return nil }
203+
200204
func (w *frameWriterRecorder) WriteFrame(frm frame.Frame) error {
201205
w.mu.Lock()
202206
defer w.mu.Unlock()

core/router/default.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type DefaultRouter struct {
1818
}
1919

2020
// Default return the DefaultRouter.
21-
func Default(functions []config.App) Router {
21+
func Default(functions []config.Function) Router {
2222
return &DefaultRouter{r: newRoute(functions)}
2323
}
2424

@@ -38,12 +38,12 @@ func (r *DefaultRouter) Clean() {
3838
}
3939

4040
type defaultRoute struct {
41-
functions []config.App
41+
functions []config.Function
4242
data map[frame.Tag]map[string]string
4343
mu sync.RWMutex
4444
}
4545

46-
func newRoute(functions []config.App) *defaultRoute {
46+
func newRoute(functions []config.Function) *defaultRoute {
4747
return &defaultRoute{
4848
functions: functions,
4949
data: make(map[frame.Tag]map[string]string),

core/router/default_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
)
1111

1212
func TestRouter(t *testing.T) {
13-
router := Default([]config.App{{Name: "sfn-1"}})
13+
router := Default([]config.Function{{Name: "sfn-1"}})
1414

1515
m := &metadata.Default{}
1616

core/server.go

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ type Server struct {
3535
router router.Router
3636
metadataDecoder metadata.Decoder
3737
counterOfDataFrame int64
38-
downstreams map[string]frame.Writer
38+
downstreams map[string]FrameWriterConnection
3939
mu sync.Mutex
4040
opts *serverOptions
4141
startHandlers []FrameHandler
@@ -58,7 +58,7 @@ func NewServer(name string, opts ...ServerOption) *Server {
5858

5959
s := &Server{
6060
name: name,
61-
downstreams: make(map[string]frame.Writer),
61+
downstreams: make(map[string]FrameWriterConnection),
6262
logger: logger,
6363
opts: options,
6464
}
@@ -68,10 +68,6 @@ func NewServer(name string, opts ...ServerOption) *Server {
6868

6969
// ListenAndServe starts the server.
7070
func (s *Server) ListenAndServe(ctx context.Context, addr string) error {
71-
if addr == "" {
72-
addr = DefaultListenAddr
73-
}
74-
7571
udpAddr, err := net.ResolveUDPAddr("udp", addr)
7672
if err != nil {
7773
return err
@@ -81,6 +77,13 @@ func (s *Server) ListenAndServe(ctx context.Context, addr string) error {
8177
return err
8278
}
8379

80+
s.logger = s.logger.With("zipper_addr", addr)
81+
82+
// connect to all downstreams.
83+
for addr, client := range s.downstreams {
84+
go client.Connect(ctx, addr)
85+
}
86+
8487
return s.Serve(ctx, conn)
8588
}
8689

@@ -104,13 +107,7 @@ func (s *Server) Serve(ctx context.Context, conn net.PacketConn) error {
104107
}
105108
s.listener = listener
106109

107-
s.logger.Info(
108-
"zipper is up and running",
109-
"pid", os.Getpid(),
110-
"quic", listener.Versions(),
111-
"auth_name", s.authNames(),
112-
"zipper_addr", s.opts.addr,
113-
)
110+
s.logger.Info("zipper is up and running", "pid", os.Getpid(), "quic", listener.Versions(), "auth_name", s.authNames())
114111

115112
for {
116113
conn, err := s.listener.Accept(ctx)
@@ -175,6 +172,10 @@ func (s *Server) Logger() *slog.Logger { return s.logger }
175172

176173
// Close will shutdown the server.
177174
func (s *Server) Close() error {
175+
// downstreams
176+
for _, ds := range s.downstreams {
177+
ds.Close()
178+
}
178179
// connector
179180
if s.connector != nil {
180181
s.connector.Close()
@@ -379,12 +380,19 @@ func (s *Server) StatsFunctions() map[string]string {
379380

380381
// StatsCounter returns how many DataFrames pass through server.
381382
func (s *Server) StatsCounter() int64 {
382-
return s.counterOfDataFrame
383+
return atomic.LoadInt64(&s.counterOfDataFrame)
383384
}
384385

385386
// Downstreams return all the downstream servers.
386-
func (s *Server) Downstreams() map[string]frame.Writer {
387-
return s.downstreams
387+
func (s *Server) Downstreams() map[string]string {
388+
s.mu.Lock()
389+
defer s.mu.Unlock()
390+
391+
snapshotOfDownstream := make(map[string]string, len(s.downstreams))
392+
for addr, client := range s.downstreams {
393+
snapshotOfDownstream[addr] = client.Name()
394+
}
395+
return snapshotOfDownstream
388396
}
389397

390398
// ConfigRouter is used to set router by zipper
@@ -413,7 +421,7 @@ func (s *Server) ConfigAlpnHandler(h func(string) error) {
413421

414422
// AddDownstreamServer add a downstream server to this server. all the DataFrames will be
415423
// dispatch to all the downstreams.
416-
func (s *Server) AddDownstreamServer(addr string, c frame.Writer) {
424+
func (s *Server) AddDownstreamServer(addr string, c FrameWriterConnection) {
417425
s.mu.Lock()
418426
s.downstreams[addr] = c
419427
s.mu.Unlock()
@@ -487,6 +495,9 @@ func (s *Server) authNames() []string {
487495
return result
488496
}
489497

498+
// Name returns the name of server.
499+
func (s *Server) Name() string { return s.name }
500+
490501
func (s *Server) doConnectionCloseHandlers(qconn quic.Connection) {
491502
for _, h := range s.connectionCloseHandlers {
492503
h(qconn)

core/server_options.go

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,13 @@ import (
99
"golang.org/x/exp/slog"
1010
)
1111

12-
const (
13-
// DefaultListenAddr is the default address to listen.
14-
DefaultListenAddr = "0.0.0.0:9000"
15-
)
16-
1712
// ServerOption is the option for server.
1813
type ServerOption func(*serverOptions)
1914

2015
// ServerOptions are the options for YoMo server.
2116
type serverOptions struct {
2217
quicConfig *quic.Config
2318
tlsConfig *tls.Config
24-
addr string
2519
auths map[string]auth.Authentication
2620
logger *slog.Logger
2721
alpnHandler func(proto string) error
@@ -33,7 +27,6 @@ func defaultServerOptions() *serverOptions {
3327
opts := &serverOptions{
3428
quicConfig: DefalutQuicConfig,
3529
tlsConfig: nil,
36-
addr: DefaultListenAddr,
3730
auths: map[string]auth.Authentication{},
3831
logger: logger,
3932
}
@@ -44,13 +37,6 @@ func defaultServerOptions() *serverOptions {
4437
return opts
4538
}
4639

47-
// WithAddr sets the server address.
48-
func WithAddr(addr string) ServerOption {
49-
return func(o *serverOptions) {
50-
o.addr = addr
51-
}
52-
}
53-
5440
// WithAuth sets the server authentication method.
5541
func WithAuth(name string, args ...string) ServerOption {
5642
return func(o *serverOptions) {

0 commit comments

Comments
 (0)