-
Notifications
You must be signed in to change notification settings - Fork 665
/
vm.go
105 lines (85 loc) · 2.98 KB
/
vm.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
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package rpcchainvm
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/health"
healthpb "google.golang.org/grpc/health/grpc_health_v1"
"github.com/ava-labs/avalanchego/snow/engine/snowman/block"
"github.com/ava-labs/avalanchego/version"
"github.com/ava-labs/avalanchego/vms/rpcchainvm/grpcutils"
"github.com/ava-labs/avalanchego/vms/rpcchainvm/gruntime"
"github.com/ava-labs/avalanchego/vms/rpcchainvm/runtime"
vmpb "github.com/ava-labs/avalanchego/proto/pb/vm"
runtimepb "github.com/ava-labs/avalanchego/proto/pb/vm/runtime"
)
const defaultRuntimeDialTimeout = 5 * time.Second
// The address of the Runtime server is expected to be passed via ENV `runtime.EngineAddressKey`.
// This address is used by the Runtime client to send Initialize RPC to server.
//
// Serve starts the RPC Chain VM server and performs a handshake with the VM runtime service.
func Serve(ctx context.Context, vm block.ChainVM, opts ...grpcutils.ServerOption) error {
signals := make(chan os.Signal, 2)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM)
server := newVMServer(vm, opts...)
go func(ctx context.Context) {
defer func() {
server.GracefulStop()
fmt.Println("vm server: graceful termination success")
}()
for {
select {
case s := <-signals:
switch s {
case syscall.SIGINT:
fmt.Println("runtime engine: ignoring signal: SIGINT")
case syscall.SIGTERM:
fmt.Println("runtime engine: received shutdown signal: SIGTERM")
return
}
case <-ctx.Done():
fmt.Println("runtime engine: context has been cancelled")
return
}
}
}(ctx)
// address of Runtime server from ENV
runtimeAddr := os.Getenv(runtime.EngineAddressKey)
if runtimeAddr == "" {
return fmt.Errorf("required env var missing: %q", runtime.EngineAddressKey)
}
clientConn, err := grpcutils.Dial(runtimeAddr)
if err != nil {
return fmt.Errorf("failed to create client conn: %w", err)
}
client := gruntime.NewClient(runtimepb.NewRuntimeClient(clientConn))
listener, err := grpcutils.NewListener()
if err != nil {
return fmt.Errorf("failed to create new listener: %w", err)
}
ctx, cancel := context.WithTimeout(ctx, defaultRuntimeDialTimeout)
defer cancel()
err = client.Initialize(ctx, version.RPCChainVMProtocol, listener.Addr().String())
if err != nil {
_ = listener.Close()
return fmt.Errorf("failed to initialize vm runtime: %w", err)
}
// start RPC Chain VM server
grpcutils.Serve(listener, server)
return nil
}
// Returns an RPC Chain VM server serving health and VM services.
func newVMServer(vm block.ChainVM, opts ...grpcutils.ServerOption) *grpc.Server {
server := grpcutils.NewServer(opts...)
vmpb.RegisterVMServer(server, NewServer(vm))
health := health.NewServer()
health.SetServingStatus("", healthpb.HealthCheckResponse_SERVING)
healthpb.RegisterHealthServer(server, health)
return server
}