Skip to content

Commit d751bb6

Browse files
3Hrenzavgorodnii
authored andcommitted
refactor: make pandora great (#657)
This commit allows to easily write ammos with custom conditions. Not to be able to add a new ammo the only logic required is to implement `Ammo` interface. Also simultaneous loading to ETH and DWH available (but not recommended).
1 parent 32793e1 commit d751bb6

13 files changed

+569
-227
lines changed

cmd/pandora/ammo.go

+19-39
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,40 @@
11
package main
22

33
import (
4-
"fmt"
4+
"context"
55
"sync"
66

77
"github.com/yandex/pandora/core"
88
)
99

10-
type AmmoFactory interface {
11-
New(id int) core.Ammo
12-
}
13-
14-
type orderInfoAmmoFactory struct {
15-
orderIDs []int64
16-
pool *sync.Pool
17-
}
18-
19-
func newOrderInfoAmmoFactory(orderIDs []int64, pool *sync.Pool) AmmoFactory {
20-
return &orderInfoAmmoFactory{
21-
orderIDs: orderIDs,
22-
pool: pool,
23-
}
24-
}
25-
26-
func (m *orderInfoAmmoFactory) New(id int) core.Ammo {
27-
orderID := m.orderIDs[id%len(m.orderIDs)]
28-
29-
ammo := m.pool.Get().(*OrderInfoAmmo)
30-
ammo.Message = fmt.Sprintf(`Job #%d %d"`, id, orderID)
31-
ammo.OrderID = orderID
10+
type AmmoType uint8
3211

33-
return ammo
34-
}
12+
type Ammo interface {
13+
core.Ammo
3514

36-
type OrderInfoAmmo struct {
37-
Message string
38-
OrderID int64
15+
// Type describes an ammo type used for pooling.
16+
// The returned value must be unique across the entire application and also
17+
// must be constant.
18+
Type() AmmoType
19+
Execute(ctx context.Context, ext interface{}) error
3920
}
4021

41-
type OrderPlaceAmmo struct {
42-
Message string
22+
type AmmoFactory interface {
23+
New(id int) Ammo
24+
NewDefault() Ammo
25+
Pool() *sync.Pool
4326
}
4427

45-
type orderPlaceAmmoFactory struct {
28+
type PoolAmmoFactory struct {
4629
pool *sync.Pool
4730
}
4831

49-
func newOrderPlaceAmmoFactory(pool *sync.Pool) AmmoFactory {
50-
return &orderPlaceAmmoFactory{
51-
pool: pool,
32+
func newPoolAmmoFactory(fn func() interface{}) PoolAmmoFactory {
33+
return PoolAmmoFactory{
34+
pool: &sync.Pool{New: fn},
5235
}
5336
}
5437

55-
func (m *orderPlaceAmmoFactory) New(id int) core.Ammo {
56-
ammo := m.pool.Get().(*OrderPlaceAmmo)
57-
ammo.Message = fmt.Sprintf(`Job #%d"`, id)
58-
59-
return ammo
38+
func (m *PoolAmmoFactory) Pool() *sync.Pool {
39+
return m.pool
6040
}

cmd/pandora/ammo_dwh.go

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package main
2+
3+
import (
4+
"context"
5+
6+
"github.com/mitchellh/mapstructure"
7+
"github.com/sonm-io/core/proto"
8+
"go.uber.org/zap"
9+
)
10+
11+
type DWHOrdersAmmo struct {
12+
order *sonm.OrdersRequest
13+
}
14+
15+
func (m *DWHOrdersAmmo) Type() AmmoType {
16+
return DWHOrders
17+
}
18+
19+
func (m *DWHOrdersAmmo) Execute(ctx context.Context, ext interface{}) error {
20+
mExt := ext.(*dwhExt)
21+
orders, err := mExt.dwh.GetOrders(ctx, m.order)
22+
if err != nil {
23+
return err
24+
}
25+
26+
mExt.log.Debug("OK", zap.String("ammo", "DWHOrders"), zap.Any("count", len(orders.Orders)))
27+
28+
return nil
29+
}
30+
31+
type dwhOrdersAmmoFactory struct {
32+
PoolAmmoFactory
33+
Orders []*sonm.OrdersRequest
34+
}
35+
36+
func newDWHOrdersAmmoFactory(cfg interface{}) (AmmoFactory, error) {
37+
config := struct {
38+
Orders []*sonm.OrdersRequest
39+
}{}
40+
if err := mapstructure.Decode(cfg, &config); err != nil {
41+
return nil, err
42+
}
43+
44+
m := &dwhOrdersAmmoFactory{
45+
PoolAmmoFactory: newPoolAmmoFactory(func() interface{} {
46+
return &DWHOrdersAmmo{}
47+
}),
48+
Orders: config.Orders,
49+
}
50+
51+
return m, nil
52+
}
53+
54+
func (m *dwhOrdersAmmoFactory) New(id int) Ammo {
55+
ammo := m.pool.Get().(*DWHOrdersAmmo)
56+
ammo.order = m.Orders[id%len(m.Orders)]
57+
58+
return ammo
59+
}
60+
61+
func (m *dwhOrdersAmmoFactory) NewDefault() Ammo {
62+
return &DWHOrdersAmmo{}
63+
}

cmd/pandora/ammo_marketplace.go

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"math/big"
6+
"math/rand"
7+
8+
"github.com/mitchellh/mapstructure"
9+
"github.com/sonm-io/core/proto"
10+
"go.uber.org/zap"
11+
)
12+
13+
const (
14+
MarketplaceOrderInfo AmmoType = iota
15+
MarketplaceOrderPlace
16+
DWHOrders
17+
)
18+
19+
type OrderInfoAmmo struct {
20+
OrderID int64
21+
}
22+
23+
func (m *OrderInfoAmmo) Type() AmmoType {
24+
return MarketplaceOrderInfo
25+
}
26+
27+
func (m *OrderInfoAmmo) Execute(ctx context.Context, ext interface{}) error {
28+
mExt := ext.(*marketplaceExt)
29+
order, err := mExt.market.GetOrderInfo(ctx, big.NewInt(m.OrderID))
30+
if err != nil {
31+
return err
32+
}
33+
34+
mExt.log.Debug("OK", zap.String("ammo", "GetOrderInfo"), zap.Any("order", *order))
35+
36+
return nil
37+
}
38+
39+
type orderInfoAmmoFactory struct {
40+
PoolAmmoFactory
41+
orderIDs []int64
42+
}
43+
44+
func newOrderInfoAmmoFactory(cfg interface{}) (AmmoFactory, error) {
45+
config := struct {
46+
OrderIDs []int64 `mapstructure:"order_ids"`
47+
}{}
48+
49+
if err := mapstructure.Decode(cfg, &config); err != nil {
50+
return nil, err
51+
}
52+
53+
m := &orderInfoAmmoFactory{
54+
PoolAmmoFactory: newPoolAmmoFactory(func() interface{} {
55+
return &OrderInfoAmmo{}
56+
}),
57+
orderIDs: config.OrderIDs,
58+
}
59+
60+
return m, nil
61+
}
62+
63+
func (m *orderInfoAmmoFactory) New(id int) Ammo {
64+
ammo := m.pool.Get().(*OrderInfoAmmo)
65+
ammo.OrderID = m.orderIDs[id%len(m.orderIDs)]
66+
67+
return ammo
68+
}
69+
70+
func (m *orderInfoAmmoFactory) NewDefault() Ammo {
71+
return &OrderInfoAmmo{}
72+
}
73+
74+
type OrderPlaceAmmo struct{}
75+
76+
func (m *OrderPlaceAmmo) Type() AmmoType {
77+
return MarketplaceOrderPlace
78+
}
79+
80+
func (m *OrderPlaceAmmo) Execute(ctx context.Context, ext interface{}) error {
81+
mExt := ext.(*marketplaceExt)
82+
orderOrError := <-mExt.market.PlaceOrder(ctx, mExt.privateKey, order())
83+
if orderOrError.Err != nil {
84+
return orderOrError.Err
85+
}
86+
87+
mExt.log.Debug("OK", zap.String("ammo", "PlaceOrder"), zap.Any("order", *orderOrError.Order))
88+
89+
return nil
90+
}
91+
92+
type orderPlaceAmmoFactory struct {
93+
PoolAmmoFactory
94+
}
95+
96+
func newOrderPlaceAmmoFactory(cfg interface{}) (AmmoFactory, error) {
97+
m := &orderPlaceAmmoFactory{
98+
PoolAmmoFactory: newPoolAmmoFactory(func() interface{} {
99+
return &OrderPlaceAmmo{}
100+
}),
101+
}
102+
103+
return m, nil
104+
}
105+
106+
func (m *orderPlaceAmmoFactory) New(id int) Ammo {
107+
return m.pool.Get().(*OrderPlaceAmmo)
108+
}
109+
110+
func (m *orderPlaceAmmoFactory) NewDefault() Ammo {
111+
return &OrderPlaceAmmo{}
112+
}
113+
114+
func order() *sonm.Order {
115+
order := &sonm.Order{
116+
OrderType: sonm.OrderType_BID,
117+
OrderStatus: sonm.OrderStatus_ORDER_ACTIVE,
118+
CounterpartyID: "0x0",
119+
Duration: 3600 + uint64(rand.Int63n(3600)),
120+
Price: sonm.NewBigIntFromInt(1000 + rand.Int63n(1000)),
121+
Netflags: sonm.NetflagsToUint([3]bool{true, true, (rand.Int() % 2) == 0}),
122+
IdentityLevel: sonm.IdentityLevel_ANONYMOUS,
123+
Blacklist: "0x0",
124+
Tag: []byte("00000"),
125+
Benchmarks: &sonm.Benchmarks{
126+
Values: []uint64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
127+
},
128+
}
129+
130+
return order
131+
}

cmd/pandora/common.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"crypto/ecdsa"
6+
"sync"
7+
8+
"github.com/sonm-io/core/accounts"
9+
"github.com/sonm-io/core/insonmnia/logging"
10+
"github.com/sonm-io/core/util"
11+
"go.uber.org/zap"
12+
"google.golang.org/grpc/credentials"
13+
)
14+
15+
var (
16+
privateKeyGlobal *ecdsa.PrivateKey
17+
privateKeyOnce sync.Once
18+
transportCredentials credentials.TransportCredentials
19+
transportCredentialsOnce sync.Once
20+
)
21+
22+
func PrivateKey(cfg EthereumConfig) *ecdsa.PrivateKey {
23+
privateKeyOnce.Do(func() {
24+
ethConfig := accounts.EthConfig{
25+
Keystore: cfg.AccountPath,
26+
Passphrase: cfg.AccountPass,
27+
}
28+
29+
privateKey, err := ethConfig.LoadKey(accounts.Silent())
30+
if err != nil {
31+
panic(err)
32+
}
33+
34+
privateKeyGlobal = privateKey
35+
})
36+
37+
return privateKeyGlobal
38+
}
39+
40+
func TransportCredentials(privateKey *ecdsa.PrivateKey) credentials.TransportCredentials {
41+
transportCredentialsOnce.Do(func() {
42+
_, TLSConfig, err := util.NewHitlessCertRotator(context.Background(), privateKey)
43+
if err != nil {
44+
panic(err)
45+
}
46+
47+
transportCredentials = util.NewTLS(TLSConfig)
48+
})
49+
50+
return transportCredentials
51+
}
52+
53+
func NewLogger(cfg LoggingConfig) (*zap.Logger, error) {
54+
level, err := logging.NewLevelFromString(cfg.Level)
55+
if err != nil {
56+
return nil, err
57+
}
58+
59+
return logging.BuildLogger(*level), nil
60+
}

cmd/pandora/config.go

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package main
2+
3+
type LoggingConfig struct {
4+
Level string `config:"level"`
5+
}
6+
7+
type EthereumConfig struct {
8+
Endpoint string `config:"endpoint"`
9+
AccountPath string `config:"account_path"`
10+
AccountPass string `config:"account_pass"`
11+
}

0 commit comments

Comments
 (0)