Skip to content

Commit

Permalink
added draft implementation for pool qubic client (#9)
Browse files Browse the repository at this point in the history
* added draft implementation for pool qubic client

* added docker build for dev branch

* properly closing and putting back conn from pool

* added rpc_server and switched deploymen to it

* added block-height

* fixed broadcast tx decode issue

* added base64 decoding to broadcast-transaction

* added encodedtx to broadcast transaction response

* bumped go-node-connector version

---------

Co-authored-by: 0xluk <luk@dev>
  • Loading branch information
0xluk and 0xluk authored Apr 17, 2024
1 parent 3c357c8 commit 9d2c2df
Show file tree
Hide file tree
Showing 29 changed files with 2,854 additions and 629 deletions.
25 changes: 25 additions & 0 deletions .github/workflows/push-docker-dev.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Deploy dev images to GHCR

on:
push:
branches:
- 'dev'

jobs:
push-store-image:
runs-on: ubuntu-latest
steps:
- name: 'Checkout GitHub Action'
uses: actions/checkout@main

- name: 'Login to GitHub Container Registry'
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{github.actor}}
password: ${{secrets.GITHUB_TOKEN}}

- name: 'Build Inventory Image'
run: |
docker build . --tag ghcr.io/qubic/qubic-http:dev
docker push ghcr.io/qubic/qubic-http:dev
File renamed without changes.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ENV CGO_ENABLED=0
WORKDIR /src
COPY . /src

RUN go build -o "./bin/server" "./app/server"
RUN go build -o "./bin/server" "./app/grpc_server"

# We don't need golang to run binaries, just use alpine.
FROM alpine
Expand Down
96 changes: 96 additions & 0 deletions app/grpc_server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package main

import (
"fmt"
"github.com/pkg/errors"
qubic "github.com/qubic/go-node-connector"
rpc "github.com/qubic/qubic-http/foundation/rpc_server"
"log"
"os"
"os/signal"
"syscall"
"time"

"github.com/ardanlabs/conf"
)

const prefix = "QUBIC_API_SIDECAR"

func main() {
log := log.New(os.Stdout, prefix, log.LstdFlags|log.Lmicroseconds|log.Lshortfile)
if err := run(log); err != nil {
log.Fatalf("main: exited with error: %s", err.Error())
}
}

func run(log *log.Logger) error {
var cfg struct {
Server struct {
ReadTimeout time.Duration `conf:"default:5s"`
WriteTimeout time.Duration `conf:"default:5s"`
ShutdownTimeout time.Duration `conf:"default:5s"`
HttpHost string `conf:"default:0.0.0.0:8000"`
GrpcHost string `conf:"default:0.0.0.0:8001"`
}
Pool struct {
NodeFetcherUrl string `conf:"default:http://127.0.0.1:8080/peers"`
NodeFetcherTimeout time.Duration `conf:"default:2s"`
InitialCap int `conf:"default:5"`
MaxIdle int `conf:"default:20"`
MaxCap int `conf:"default:30"`
IdleTimeout time.Duration `conf:"default:15s"`
}
}

if err := conf.Parse(os.Args[1:], prefix, &cfg); err != nil {
switch err {
case conf.ErrHelpWanted:
usage, err := conf.Usage(prefix, &cfg)
if err != nil {
return errors.Wrap(err, "generating config usage")
}
fmt.Println(usage)
return nil
case conf.ErrVersionWanted:
version, err := conf.VersionString(prefix, &cfg)
if err != nil {
return errors.Wrap(err, "generating config version")
}
fmt.Println(version)
return nil
}
return errors.Wrap(err, "parsing config")
}

out, err := conf.String(&cfg)
if err != nil {
return errors.Wrap(err, "generating config for output")
}
log.Printf("main: Config :\n%v\n", out)

pool, err := qubic.NewPoolConnection(qubic.PoolConfig{
InitialCap: cfg.Pool.InitialCap,
MaxCap: cfg.Pool.MaxCap,
MaxIdle: cfg.Pool.MaxIdle,
IdleTimeout: cfg.Pool.IdleTimeout,
NodeFetcherUrl: cfg.Pool.NodeFetcherUrl,
NodeFetcherTimeout: cfg.Pool.NodeFetcherTimeout,
NodePort: "21841",
})
if err != nil {
return errors.Wrap(err, "creating qubic pool")
}

rpcServer := rpc.NewServer(cfg.Server.GrpcHost, cfg.Server.HttpHost, pool)
rpcServer.Start()

shutdown := make(chan os.Signal, 1)
signal.Notify(shutdown, os.Interrupt, syscall.SIGTERM)

for {
select {
case <-shutdown:
return errors.New("shutting down")
}
}
}
18 changes: 11 additions & 7 deletions app/server/docs/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
// swagger-ui:route GET /v1/send-tx tx send-tx
// Send signed transaction.
// responses:
// 201: sendSignedTransactionResponse
//
// 201: sendSignedTransactionResponse
//
// Send signed transaction
// swagger-ui:response sendSignedTransactionResponse
type sendSignedTransactionResponse struct {
Expand All @@ -25,16 +27,18 @@ type sendTxRequest struct {
// swagger-ui:route POST /v1/get-tx-status tx get-tx-status
// Get transaction status
// responses:
// 200: getTransactionStatusResponse
//
// 200: getTransactionStatusResponse
//
// Get transaction status
// swagger-ui:response getTransactionStatusResponse
type getTransactionStatusResponse struct {
//in:body
Body tick.GetTickDataOutput
}

// swagger-ui:parameters get-tx-status
type getTransactionStatusRequest struct {
// in:body
Body tx.GetTxStatusInput
}
//// swagger-ui:parameters get-tx-status
//type getTransactionStatusRequest struct {
// // in:body
// Body tx.GetTxStatusInput
//}
15 changes: 7 additions & 8 deletions app/server/handlers/handlers.go
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
package handlers

import (
qubic "github.com/qubic/go-node-connector"
_ "github.com/qubic/qubic-http/app/server/docs"
"github.com/qubic/qubic-http/business/mid"
"github.com/qubic/qubic-http/business/mid"
"github.com/qubic/qubic-http/external/opensearch"
"github.com/qubic/qubic-http/foundation/nodes"
"github.com/qubic/qubic-http/foundation/web"
"log"
"net/http"
"os"
)

func New(shutdown chan os.Signal, log *log.Logger, pool *nodes.Pool, osclient *opensearch.Client) http.Handler {
func New(shutdown chan os.Signal, log *log.Logger, pool *qubic.Pool, osclient *opensearch.Client) http.Handler {
app := web.NewApp(shutdown, mid.Logger(log), mid.Errors(log), mid.Metrics(), mid.Panics(log))

ih := identitiesHandler{pool: pool}
app.Handle(http.MethodGet, "/v1/address/:identity", ih.One)

th := tickHandler{pool: pool, opensearchClient: osclient}
th := tickHandler{pool: pool}
app.Handle(http.MethodGet, "/v1/tick-info", th.GetTickInfo)
//app.Handle(http.MethodGet, "/v1/tick-transactions/:tick", th.GetTickTransactions)
//app.Handle(http.MethodGet, "/v1/tick-data/:tick", th.GetTickData)

app.Handle(http.MethodGet, "/v1/tick-data/:tick", th.GetTickDataV2)
app.Handle(http.MethodGet, "/v1/quorum/:tick", th.GetQuorum)
app.Handle(http.MethodGet, "/v1/computors/:epoch", th.GetComputors)
//app.Handle(http.MethodGet, "/v1/tick-data/:tick", th.GetTickDataV2)
//app.Handle(http.MethodGet, "/v1/quorum/:tick", th.GetQuorum)
//app.Handle(http.MethodGet, "/v1/computors/:epoch", th.GetComputors)

txH := txHandler{pool: pool, opensearchClient: osclient}
app.Handle(http.MethodPost, "/v1/send-raw-tx", txH.SendRawTx)
Expand All @@ -35,6 +35,5 @@ func New(shutdown chan os.Signal, log *log.Logger, pool *nodes.Pool, osclient *o
sh := statusHandler{opensearchClient: osclient}
app.Handle(http.MethodGet, "/v1/status", sh.GetStatus)


return app
}
32 changes: 24 additions & 8 deletions app/server/handlers/identities.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,41 @@ package handlers

import (
"context"
"github.com/0xluk/go-qubic/foundation/tcp"
"github.com/pkg/errors"
qubic "github.com/qubic/go-node-connector"
"github.com/qubic/qubic-http/business/data/identity"
"github.com/qubic/qubic-http/foundation/nodes"
"github.com/qubic/qubic-http/foundation/web"
"log"
"net/http"
)

type identitiesHandler struct {
pool *nodes.Pool
pool *qubic.Pool
}

func (h *identitiesHandler) One(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
ip := h.pool.GetRandomIP()
qc, err := tcp.NewQubicConnection(ctx, ip, "21841")
var err error
qc, err := h.pool.Get()
if err != nil {
return web.RespondError(ctx, w, errors.Wrap(err, "creating qubic conn"))
return web.RespondError(ctx, w, errors.Wrap(err, "getting qubic conn from pool"))
}

defer func() {
if err == nil {
log.Printf("Putting conn back to pool")
pErr := h.pool.Put(qc)
if pErr != nil {
log.Printf("Putting conn back to pool failed: %s", pErr.Error())
}
} else {
log.Printf("Closing conn")
cErr := h.pool.Close(qc)
if cErr != nil {
log.Printf("Closing conn failed: %s", cErr.Error())
}
}
}()

params := web.Params(r)
id, ok := params["identity"]
if !ok {
Expand All @@ -30,6 +47,5 @@ func (h *identitiesHandler) One(ctx context.Context, w http.ResponseWriter, r *h
if err != nil {
return web.RespondError(ctx, w, errors.Wrap(err, "getting balance"))
}

return web.Respond(ctx, w, res, http.StatusOK)
}
}
Loading

0 comments on commit 9d2c2df

Please sign in to comment.