Skip to content

Commit

Permalink
added coin-distribution structure
Browse files Browse the repository at this point in the history
  • Loading branch information
ice-ares committed Nov 30, 2023
1 parent 4d8d5aa commit e19be03
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 6 deletions.
28 changes: 28 additions & 0 deletions cmd/freezer-coin-distributer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# SPDX-License-Identifier: ice License 1.0

FROM golang:latest AS build
ARG SERVICE_NAME
ARG TARGETOS
ARG TARGETARCH

WORKDIR /app/
COPY . /app/

ENV CGO_ENABLED=0
ENV GOOS=$TARGETOS
ENV GOARCH=$TARGETARCH

RUN env SERVICE_NAME=$SERVICE_NAME make dockerfile
RUN cp cmd/$SERVICE_NAME/bin bin

FROM gcr.io/distroless/base-debian11:latest
ARG TARGETOS
ARG TARGETARCH
ARG PORT=443
LABEL os=$TARGETOS
LABEL arch=$TARGETARCH
COPY --from=build /app/bin app
#You might need to expose more ports. Just add more separated by space
#I.E. EXPOSE 8080 8081 8082 8083
EXPOSE $PORT
ENTRYPOINT ["/app"]
50 changes: 50 additions & 0 deletions cmd/freezer-coin-distributer/freezer_coin_distributer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: ice License 1.0

package main

import (
"context"
"fmt"

"github.com/pkg/errors"

coindistribution "github.com/ice-blockchain/freezer/coin-distribution"
appCfg "github.com/ice-blockchain/wintr/config"
"github.com/ice-blockchain/wintr/log"
"github.com/ice-blockchain/wintr/server"
)

func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

const pkgName = "cmd/freezer-coin-distributer"

var cfg struct{ Version string }
appCfg.MustLoadFromKey(pkgName, &cfg)

log.Info(fmt.Sprintf("starting version `%v`...", cfg.Version))

server.New(new(service), pkgName, "").ListenAndServe(ctx, cancel)
}

type (
// | service implements server.State and is responsible for managing the state and lifecycle of the package.
service struct{ coinDistributer coindistribution.Client }
)

func (s *service) RegisterRoutes(_ *server.Router) {}

func (s *service) Init(ctx context.Context, cancel context.CancelFunc) {
s.coinDistributer = coindistribution.MustStartCoinDistribution(ctx, cancel)
}

func (s *service) Close(_ context.Context) error {
return errors.Wrap(s.coinDistributer.Close(), "could not close service")
}

func (s *service) CheckHealth(ctx context.Context) error {
log.Debug("checking health...", "package", "coin-distribution")

return errors.Wrap(s.coinDistributer.CheckHealth(ctx), "failed to check coin distributer's health")
}
18 changes: 18 additions & 0 deletions coin-distribution/.testdata/application.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# SPDX-License-Identifier: ice License 1.0

development: true
logger:
encoder: console
level: debug
coin-distribution:
development: true
workers: 10
batchSize: 100
wintr/connectors/storage/v2:
runDDL: true
primaryURL: postgresql://root:pass@localhost:5433/freezer
credentials:
user: root
password: pass
replicaURLs:
- postgresql://root:pass@localhost:5433/freezer
23 changes: 23 additions & 0 deletions coin-distribution/DDL.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-- SPDX-License-Identifier: ice License 1.0
CREATE TABLE IF NOT EXISTS pending_coin_distributions (
created_at timestamp NOT NULL,
internal_id bigint NOT NULL,
iceflakes bigint NOT NULL,
user_id text NOT NULL PRIMARY KEY,
eth_address text NOT NULL);

CREATE INDEX IF NOT EXISTS pending_coin_distributions_worker_number_ix ON pending_coin_distributions ((internal_id % 10), created_at ASC);

--- Flow:
--infinite loop: -- with 30 sec sleep between iterations if 0 rows returned
--do in transaction:
--1. SELECT *
-- FROM pending_coin_distributions
-- WHERE internal_id % 10 = $1
-- ORDER BY created_at ASC
-- LIMIT $2
-- FOR UPDATE
--2. call ERC-20 smart contract method to airdrop coins
--3. delete from pending_coin_distributions WHERE user_id = ANY($1)
-- if transaction fails you retry infinitely
-- log.info every successful transaction, log every error
55 changes: 55 additions & 0 deletions coin-distribution/coin_distribution.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// SPDX-License-Identifier: ice License 1.0

package coindistribution

import (
"context"
"sync"

"github.com/hashicorp/go-multierror"
"github.com/pkg/errors"

appCfg "github.com/ice-blockchain/wintr/config"
"github.com/ice-blockchain/wintr/connectors/storage/v2"
)

func init() {
appCfg.MustLoadFromKey(applicationYamlKey, &cfg)
}

func MustStartCoinDistribution(ctx context.Context, cancel context.CancelFunc) Client {
cd := &coinDistributer{
db: storage.MustConnect(context.Background(), ddl, applicationYamlKey),
wg: new(sync.WaitGroup),
}
cd.wg.Add(int(cfg.Workers))
cd.cancel = cancel

for workerNumber := int64(0); workerNumber < cfg.Workers; workerNumber++ {
go func(wn int64) {
defer cd.wg.Done()
cd.distributeCoins(ctx, wn)
}(workerNumber)
}

return cd
}

func (cd *coinDistributer) Close() error {
cd.cancel()
cd.wg.Wait()

return multierror.Append(
errors.Wrap(cd.db.Close(), "failed to close db"),
).ErrorOrNil()
}

func (cd *coinDistributer) CheckHealth(ctx context.Context) error {
return errors.Wrap(cd.db.Ping(ctx), "[health-check] failed to ping DB")
}

func (cd *coinDistributer) distributeCoins(ctx context.Context, workerNumber int64) {
for ctx.Err() == nil {
println(workerNumber)
}
}
48 changes: 48 additions & 0 deletions coin-distribution/contract.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: ice License 1.0

package coindistribution

import (
"context"
_ "embed"
"io"
"sync"

"github.com/ice-blockchain/wintr/connectors/storage/v2"
)

// Public API.

type (
Client interface {
io.Closer
CheckHealth(context.Context) error
}
)

// Private API.

const (
applicationYamlKey = "coin-distribution"
)

// .
var (
//nolint:gochecknoglobals // Singleton & global config mounted only during bootstrap.
cfg config
//go:embed DDL.sql
ddl string
)

type (
coinDistributer struct {
db *storage.DB
cancel context.CancelFunc
wg *sync.WaitGroup
}
config struct {
Workers int64 `yaml:"workers"`
BatchSize int64 `yaml:"batchSize"`
Development bool `yaml:"development"`
}
)
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/cenkalti/backoff/v4 v4.2.1
github.com/goccy/go-json v0.10.2
github.com/hashicorp/go-multierror v1.1.1
github.com/ice-blockchain/eskimo v1.190.0
github.com/ice-blockchain/eskimo v1.193.0
github.com/ice-blockchain/go-tarantool-client v0.0.0-20230327200757-4fc71fa3f7bb
github.com/ice-blockchain/wintr v1.125.0
github.com/imroc/req/v3 v3.42.2
Expand Down Expand Up @@ -137,7 +137,7 @@ require (
github.com/twmb/franz-go v1.15.2 // indirect
github.com/twmb/franz-go/pkg/kadm v1.10.0 // indirect
github.com/twmb/franz-go/pkg/kmsg v1.7.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
go.opencensus.io v0.24.0 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,8 @@ github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mO
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/ice-blockchain/eskimo v1.190.0 h1:1pU/fZvoJYywuQ8A9zmRzjiXkjWWaZ1b3EWqf0XXac4=
github.com/ice-blockchain/eskimo v1.190.0/go.mod h1:zvDU+xukTh7ZmCLi4wFsnrl8LlcTg+9mYrEoyL2f7hw=
github.com/ice-blockchain/eskimo v1.193.0 h1:0U1E7NOpoKvY2y8OvNDKggHlciuEwYsPJ4xrFu7FXHI=
github.com/ice-blockchain/eskimo v1.193.0/go.mod h1:3hnl49K1NMs8WY+W2MXTw5rJjrvj8WxOaVQnqXMgSiA=
github.com/ice-blockchain/go-tarantool-client v0.0.0-20230327200757-4fc71fa3f7bb h1:8TnFP3mc7O+tc44kv2e0/TpZKnEVUaKH+UstwfBwRkk=
github.com/ice-blockchain/go-tarantool-client v0.0.0-20230327200757-4fc71fa3f7bb/go.mod h1:ZsQU7i3mxhgBBu43Oev7WPFbIjP4TniN/b1UPNGbrq8=
github.com/ice-blockchain/wintr v1.125.0 h1:pk/SVyztstUF19+JDCufJRMXJeNpchVA4O26xp47l3Y=
Expand Down Expand Up @@ -374,8 +374,8 @@ github.com/twmb/franz-go/pkg/kadm v1.10.0 h1:3oYKNP+e3HGo4GYadrDeRxOaAIsOXmX6LBV
github.com/twmb/franz-go/pkg/kadm v1.10.0/go.mod h1:hUMoV4SRho+2ij/S9cL39JaLsr+XINjn0ZkCdBY2DXc=
github.com/twmb/franz-go/pkg/kmsg v1.7.0 h1:a457IbvezYfA5UkiBvyV3zj0Is3y1i8EJgqjJYoij2E=
github.com/twmb/franz-go/pkg/kmsg v1.7.0/go.mod h1:se9Mjdt0Nwzc9lnjJ0HyDtLyBnaBDAd7pCje47OhSyw=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
Expand Down

0 comments on commit e19be03

Please sign in to comment.