Skip to content

Commit

Permalink
Move app initialization code to a weaver.Main method. (#359)
Browse files Browse the repository at this point in the history
* Move app initialization code to a weaver.Main method.

Previously, application startup code was wrapped up in a function
passed to weaver.Run. However this made it hard to test startup
code. We now have a `Main` method in `weaver.Main` and place the
startup code in the implementation of this method.

Refactored startup the internal API used by weavertest to separate out
starting the application from running its startup code.

* Disallow "weaver.Ref[weaver.Main]" component fields.

* Drop TODO and add comment for Main
  • Loading branch information
ghemawat committed May 30, 2023
1 parent 89ff04b commit 570d1ee
Show file tree
Hide file tree
Showing 31 changed files with 946 additions and 143 deletions.
30 changes: 17 additions & 13 deletions component.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package weaver

import (
"context"
"crypto/tls"
"net"
"sync"
Expand Down Expand Up @@ -116,8 +117,13 @@ type component struct {
var _ Instance = &componentImpl{}

// Main is interface implemented by an application's main component.
// This component is created automatically by `weaver.Run`.
type Main interface{}
// This component is instantiated and its Main() method called by
// `weaver.Run`.
type Main interface {
// Main contains the application main. It typically loops
// forever, e.g., inside http.Serve.
Main(context.Context) error
}

// Implements[T] is a type that can be embedded inside a component implementation
// struct to indicate that the struct implements a component of type T. E.g.,
Expand Down Expand Up @@ -174,17 +180,15 @@ func (r Ref[T]) isRef() {}
// A Listener implements the net.Listener interface, so you can use a Listener
// wherever you use a net.Listener. For example,
//
// weaver.Run(..., func(..., s *server) {
// lis, err := s.Listener("hello", weaver.ListenerOptions{})
// if err != nil {
// log.Fatal(err)
// }
// s.Logger().Info("Listener available at %v", lis)
// http.HandleFunc("/a", func(http.ResponseWriter, *http.Request) {...})
// http.HandleFunc("/b", func(http.ResponseWriter, *http.Request) {...})
// http.HandleFunc("/c", func(http.ResponseWriter, *http.Request) {...})
// http.Serve(lis, nil)
// })
// lis, err := s.Listener("hello", weaver.ListenerOptions{})
// if err != nil {
// log.Fatal(err)
// }
// s.Logger().Info("Listener available at %v", lis)
// http.HandleFunc("/a", func(http.ResponseWriter, *http.Request) {...})
// http.HandleFunc("/b", func(http.ResponseWriter, *http.Request) {...})
// http.HandleFunc("/c", func(http.ResponseWriter, *http.Request) {...})
// http.Serve(lis, nil)
type Listener struct {
net.Listener // underlying listener
proxyAddr string // address of proxy that forwards to the listener
Expand Down
2 changes: 1 addition & 1 deletion examples/chat/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ import (

func main() {
flag.Parse()
weaver.Run(context.Background(), serve)
weaver.Run(context.Background())
}
2 changes: 1 addition & 1 deletion examples/chat/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ type server struct {
cache weaver.Ref[LocalCache]
}

func serve(ctx context.Context, s *server) error {
func (s *server) Main(ctx context.Context) error {
s.httpServer.Handler = instrument(s.label, s)
lis, err := s.Listener("chat", weaver.ListenerOptions{LocalAddress: *flagAddress})
if err != nil {
Expand Down
93 changes: 91 additions & 2 deletions examples/chat/weaver_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/collatz/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ var localAddr = flag.String("local_addr", "localhost:9000", "Collatz server loca

func main() {
flag.Parse()
if err := weaver.Run(context.Background(), serve); err != nil {
if err := weaver.Run(context.Background()); err != nil {
log.Fatal(err)
}
}
2 changes: 1 addition & 1 deletion examples/collatz/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type server struct {
even weaver.Ref[Even]
}

func serve(ctx context.Context, s *server) error {
func (s *server) Main(ctx context.Context) error {
s.mux.Handle("/", weaver.InstrumentHandlerFunc("collatz", s.handle))
s.mux.HandleFunc(weaver.HealthzURL, weaver.HealthzHandler)
lis, err := s.Listener("collatz", weaver.ListenerOptions{LocalAddress: *localAddr})
Expand Down
93 changes: 91 additions & 2 deletions examples/collatz/weaver_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/factors/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ var localAddr = flag.String("local_addr", "localhost:9000", "Local address")
func main() {
flag.Parse()
ctx := context.Background()
if err := weaver.Run(ctx, serve); err != nil {
if err := weaver.Run(ctx); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
Expand Down
2 changes: 1 addition & 1 deletion examples/factors/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type server struct {
factorer weaver.Ref[Factorer]
}

func serve(ctx context.Context, s *server) error {
func (s *server) Main(ctx context.Context) error {
http.Handle("/", weaver.InstrumentHandlerFunc("/", s.handleFactors))

lis, err := s.Listener("factors", weaver.ListenerOptions{LocalAddress: *localAddr})
Expand Down
Loading

0 comments on commit 570d1ee

Please sign in to comment.