Serve starts a dRPC connection for the provisioner and transport provided.
(ctx context.Context, server Server, options *ServeOptions)
| 50 | |
| 51 | // Serve starts a dRPC connection for the provisioner and transport provided. |
| 52 | func Serve(ctx context.Context, server Server, options *ServeOptions) error { |
| 53 | if options == nil { |
| 54 | options = &ServeOptions{} |
| 55 | } |
| 56 | if options.Listener != nil && options.Conn != nil { |
| 57 | return xerrors.New("specify Listener or Conn, not both") |
| 58 | } |
| 59 | // Default to using stdio with yamux as a Listener |
| 60 | if options.Listener == nil && options.Conn == nil { |
| 61 | config := yamux.DefaultConfig() |
| 62 | config.LogOutput = io.Discard |
| 63 | stdio, err := yamux.Server(&readWriteCloser{ |
| 64 | ReadCloser: os.Stdin, |
| 65 | Writer: os.Stdout, |
| 66 | }, config) |
| 67 | if err != nil { |
| 68 | return xerrors.Errorf("create yamux: %w", err) |
| 69 | } |
| 70 | go func() { |
| 71 | <-ctx.Done() |
| 72 | _ = stdio.Close() |
| 73 | }() |
| 74 | options.Listener = stdio |
| 75 | } |
| 76 | if options.WorkDirectory == "" { |
| 77 | var err error |
| 78 | options.WorkDirectory, err = os.MkdirTemp("", "coderprovisioner") |
| 79 | if err != nil { |
| 80 | return xerrors.Errorf("failed to init temp work dir: %w", err) |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | // dRPC is a drop-in replacement for gRPC with less generated code, and faster transports. |
| 85 | // See: https://www.storj.io/blog/introducing-drpc-our-replacement-for-grpc |
| 86 | mux := drpcmux.New() |
| 87 | ps := &protoServer{ |
| 88 | server: server, |
| 89 | opts: *options, |
| 90 | } |
| 91 | err := proto.DRPCRegisterProvisioner(mux, ps) |
| 92 | if err != nil { |
| 93 | return xerrors.Errorf("register provisioner: %w", err) |
| 94 | } |
| 95 | srv := drpcserver.NewWithOptions(&tracing.DRPCHandler{Handler: mux}, drpcserver.Options{ |
| 96 | Manager: drpcsdk.DefaultDRPCOptions(nil), |
| 97 | }) |
| 98 | |
| 99 | if options.Listener != nil { |
| 100 | err = srv.Serve(ctx, options.Listener) |
| 101 | } else if options.Conn != nil { |
| 102 | err = srv.ServeOne(ctx, options.Conn) |
| 103 | } |
| 104 | if err != nil { |
| 105 | if errors.Is(err, io.EOF) || |
| 106 | errors.Is(err, context.Canceled) || |
| 107 | errors.Is(err, io.ErrClosedPipe) || |
| 108 | errors.Is(err, yamux.ErrSessionShutdown) || |
| 109 | errors.Is(err, fasthttputil.ErrInmemoryListenerClosed) { |