Skip to content

Commit

Permalink
Handle health check using dGRPC and add a first documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
ArnaudBger committed Feb 12, 2024
1 parent 3fc0c43 commit 3cc01ca
Show file tree
Hide file tree
Showing 5 changed files with 768 additions and 20 deletions.
118 changes: 118 additions & 0 deletions server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Block Meta Service API Documentation

## Overview

The Block Meta Service API provides a set of gRPC services for querying blockchain block metadata. It enables users to retrieve block IDs using block numbers, convert block IDs to block numbers, fetch the latest block information, and query blocks by specific timestamps.

## Services

### Block Service

The `Block` service offers functionalities to map block numbers to block IDs, block IDs to their corresponding block numbers, and to retrieve the latest block information.

#### RPC Methods

- `NumToID(NumToIDReq)`: Given a block number, returns the block ID, number, and timestamp.
- `IDToNum(IDToNumReq)`: Given a block ID, returns the block ID, number, and timestamp.
- `Head(Empty)`: Returns the latest block's ID, number, and timestamp.

### BlockByTime Service

The `BlockByTime` service provides capabilities to query block information based on specific timestamps.

#### RPC Methods

- `At(TimeReq)`: Returns the block closest to a specified timestamp.
- `After(RelativeTimeReq)`: Returns the first block after a specified timestamp (or the block at the specified timestamp if it exists, if the query is inclusive).
- `Before(RelativeTimeReq)`: Returns the last block before a specified timestamp (or the block at the specified timestamp if it exists, if the query is inclusive).

## Message Types

### Requests

- `NumToIDReq`: Request containing a block number (field: `blockNum`, type: `uint64`).
- `IDToNumReq`: Request containing a block ID (field: `blockID`, type: `string`).
- `TimeReq`: Request containing a specific timestamp (field: `time`, type: `google.protobuf.Timestamp`).
- `RelativeTimeReq`: Request containing a timestamp ((field: `time` , type: `google.protobuf.Timestamp`) , (field:`inclusive`, type: `bool`)) and a boolean indicating whether the query is inclusive of the given timestamp.

### Responses

- `BlockResp`: Response containing a block's ID (`string`), number (`uint64`), and timestamp (`google.protobuf.Timestamp`).

## Endpoints

To interact with the Block Meta Service, clients should use the following gRPC endpoints:

- `BlockServiceEndpoint`:
- `BlockByTimeServiceEndpoint`:

## Example Query and Response

### Querying block information using a block number

```
grpcurl --plaintext -proto server/proto/sf/blockmeta/v2/blockmeta.proto -d '{"blockNum": "501"}' localhost:9000 sf.blockmeta.v2.Block/NumToID
```

```json
{
}
```

### Querying block information using a block ID

```
grpcurl --plaintext -proto server/proto/sf/blockmeta/v2/blockmeta.proto -d '{"blockID": "501"}' localhost:9000 sf.blockmeta.v2.Block/IDToNum
```

```json
{
}
```

### Querying head block information

```
grpcurl --plaintext -proto server/proto/sf/blockmeta/v2/blockmeta.proto localhost:9000 sf.blockmeta.v2.Block/Head
```

```json
{
}
```

### Querying block information at a specific timestamp

```
grpcurl --plaintext -proto server/proto/sf/blockmeta/v2/blockmeta.proto -d '{"time": ""}' localhost:9000 sf.blockmeta.v2.BlockByTime/At
```

```json
{
}
```

### Querying block information after a specific timestamp by setting inclusive to true

```
grpcurl --plaintext -proto server/proto/sf/blockmeta/v2/blockmeta.proto -d '{"time": "", "inclusive": "true"}' localhost:9000 sf.blockmeta.v2.BlockByTime/After
```

```json
{
}
```
### Querying block information before a specific timestamp by setting inclusive to false

```
grpcurl --plaintext -proto server/proto/sf/blockmeta/v2/blockmeta.proto -d '{"time": , "inclusive": "false"}' localhost:9000 sf.blockmeta.v2.BlockByTime/Before
```

```json
{
}
```


//TODO: DO NOT FORGET TO SAY THIS API IS CHAIN AGNOSTIC
48 changes: 30 additions & 18 deletions server/cmd/blockmeta/main.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,28 @@
package main

import (
"context"
"flag"
"fmt"
"net"
"github.com/streamingfast/dgrpc/server/factory"
"go.uber.org/zap"
"google.golang.org/grpc"
"os"
"time"

pbbmsrv "github.com/streamingfast/blockmeta-service/pb/sf/blockmeta/v2"
"github.com/streamingfast/blockmeta-service/service"
"google.golang.org/grpc"
derr "github.com/streamingfast/derr"
dgrpcserver "github.com/streamingfast/dgrpc/server"
)

var (
listenAddress = flag.String("grpc-listen-addr", ":9000", "The gRPC server listen address")
listenAddress = flag.String("grpc-listen-addr", "", "The gRPC server listen address")
sinkServerAddress = flag.String("sink-addr", "", "The sink server address")
)

// todo: convert to cobra and viper
func main() {
flag.Parse()

listener, err := net.Listen("tcp", fmt.Sprintf("%s", *listenAddress))
if err != nil {
logger.Error("failed to listen", "error", err, "address", *listenAddress)
os.Exit(1)
}

if *sinkServerAddress == "" {
logger.Error("sink server address is required")
os.Exit(1)
Expand All @@ -35,13 +32,28 @@ func main() {
blockService := service.NewBlockService(sinkClient)
blockByTimeService := service.NewBlockByTimeService(sinkClient)

sBlock := grpc.NewServer()
pbbmsrv.RegisterBlockServer(sBlock, blockService)
pbbmsrv.RegisterBlockByTimeServer(sBlock, blockByTimeService)
options := []dgrpcserver.Option{
dgrpcserver.WithLogger(zap.NewNop()),
dgrpcserver.WithHealthCheck(dgrpcserver.HealthCheckOverGRPC|dgrpcserver.HealthCheckOverHTTP, healthCheck()),
}

grpcServer := factory.ServerFromOptions(options...)

logger.Info("server block listening", "address", listener.Addr())
if err := sBlock.Serve(listener); err != nil {
logger.Error("failed to serve", "error", err)
os.Exit(1)
grpcServer.RegisterService(func(gs grpc.ServiceRegistrar) {
pbbmsrv.RegisterBlockServer(gs, blockService)
pbbmsrv.RegisterBlockByTimeServer(gs, blockByTimeService)
})

go grpcServer.Launch(*listenAddress)
<-derr.SetupSignalHandler(30 * time.Second)

}

func healthCheck() dgrpcserver.HealthCheck {
return func(ctx context.Context) (isReady bool, out interface{}, err error) {
if derr.IsShuttingDown() {
return false, nil, nil
}
return true, nil, nil
}
}
12 changes: 11 additions & 1 deletion server/cmd/tester/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"context"
"flag"
"fmt"
"log"
"time"
Expand All @@ -11,8 +12,17 @@ import (
"google.golang.org/protobuf/types/known/timestamppb"
)

var (
serverAddress = flag.String("server-addr", "localhost:50051", "The server address")
)

func main() {
conn, err := dgrpc.NewInternalClient("localhost:50051")
flag.Parse()
if *serverAddress == "" {
log.Fatalf("You must provide a server address using the -server-addr flag.")
}

conn, err := dgrpc.NewInternalClient(*serverAddress)
if err != nil {
log.Fatalf("did not connect: %v", err)
}
Expand Down
65 changes: 65 additions & 0 deletions server/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,91 @@ module github.com/streamingfast/blockmeta-service
go 1.21

require (
github.com/streamingfast/derr v0.0.0-20230515163924-8570aaa43fe1
github.com/streamingfast/dgrpc v0.0.0-20240119162453-69517bcc1a7f
google.golang.org/grpc v1.58.0
google.golang.org/protobuf v1.32.0
)

require (
cloud.google.com/go/compute v1.21.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/container v1.22.1 // indirect
cloud.google.com/go/monitoring v1.15.1 // indirect
cloud.google.com/go/trace v1.10.1 // indirect
contrib.go.opencensus.io/exporter/stackdriver v0.12.6 // indirect
contrib.go.opencensus.io/exporter/zipkin v0.1.1 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v0.32.3 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.15.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.39.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/propagator v0.0.0-20221018185641-36f91511cfd7 // indirect
github.com/aws/aws-sdk-go v1.22.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blendle/zapdriver v1.3.1 // indirect
github.com/bufbuild/connect-go v1.8.0 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect
github.com/envoyproxy/go-control-plane v0.11.1 // indirect
github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/s2a-go v0.1.4 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
github.com/googleapis/gax-go/v2 v2.11.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 // indirect
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.0 // indirect
github.com/rs/cors v1.8.3 // indirect
github.com/sethvargo/go-retry v0.2.3 // indirect
github.com/streamingfast/dtracing v0.0.0-20210811175635-d55665d3622a // indirect
github.com/streamingfast/logging v0.0.0-20220304214715-bc750a74b424 // indirect
github.com/streamingfast/sf-tracing v0.0.0-20230616174903-cd2ade641ca9 // indirect
github.com/streamingfast/shutter v1.5.0 // indirect
github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.9.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.4 // indirect
go.opentelemetry.io/otel v1.16.0 // indirect
go.opentelemetry.io/otel/exporters/jaeger v1.15.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.15.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.15.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.15.1 // indirect
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.15.1 // indirect
go.opentelemetry.io/otel/exporters/zipkin v1.15.1 // indirect
go.opentelemetry.io/otel/metric v1.16.0 // indirect
go.opentelemetry.io/otel/sdk v1.16.0 // indirect
go.opentelemetry.io/otel/trace v1.16.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/oauth2 v0.10.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/term v0.10.0 // indirect
golang.org/x/text v0.11.0 // indirect
google.golang.org/api v0.126.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
)
Loading

0 comments on commit 3cc01ca

Please sign in to comment.