Skip to content
This repository was archived by the owner on Sep 12, 2019. It is now read-only.

Commit 2c3d9b4

Browse files
committed
Database drivers
1 parent 73e94ec commit 2c3d9b4

File tree

16 files changed

+578
-209
lines changed

16 files changed

+578
-209
lines changed

README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ The `config.toml` file must be present in a working directory. Config file shoul
1717

1818
* `port` - server listening port
1919
* `api_key` - when set, all requests to gateway server must contain `api_key` parameter with a correct value, otherwise the server will respond with `503 Forbidden`
20-
* `network_passphrase` - passphrase of the network that will be used with this gateway server, default: `Test SDF Network ; September 2015`
20+
* `network_passphrase` - passphrase of the network that will be used with this gateway server:
21+
* test network: `Test SDF Network ; September 2015`
22+
* public network: `Public Global Stellar Network ; September 2015`
2123
* `horizon` - URL to [horizon](https://github.com/stellar/horizon) server instance
2224
* `assets` - array of approved assets codes that this server can authorize and send
2325
* `database`
24-
* `type` - database type (sqlite3, mysql, postgres)
26+
* `type` - database type (mysql, postgres)
2527
* `url` - url to database connection
2628
* `accounts`
2729
* `authorizing_seed` - secret seed of the account to send `allow_trust` operations
@@ -33,6 +35,13 @@ The `config.toml` file must be present in a working directory. Config file shoul
3335

3436
Check [`config-example.toml`](./config-example.toml).
3537

38+
The minimal set of config values contains:
39+
* `port`
40+
* `network_passphrase`
41+
* `horizon`
42+
43+
It will start a server with a single endpoint: `/payment`.
44+
3645
## Getting started
3746

3847
After creating `config.toml` file, you need to run DB migrations:

src/github.com/stellar/gateway/app.go

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ import (
55
"flag"
66
"fmt"
77
log "github.com/Sirupsen/logrus"
8+
"os"
89
"time"
910

1011
"github.com/stellar/gateway/config"
1112
"github.com/stellar/gateway/db"
13+
"github.com/stellar/gateway/db/drivers/mysql"
14+
"github.com/stellar/gateway/db/drivers/postgres"
1215
"github.com/stellar/gateway/handlers"
1316
"github.com/stellar/gateway/horizon"
1417
"github.com/stellar/gateway/listener"
@@ -19,31 +22,62 @@ import (
1922

2023
type App struct {
2124
config config.Config
25+
driver db.Driver
2226
entityManager db.EntityManagerInterface
2327
horizon horizon.HorizonInterface
2428
transactionSubmitter *submitter.TransactionSubmitter
2529
repository db.RepositoryInterface
2630
}
2731

2832
// NewApp constructs an new App instance from the provided config.
29-
func NewApp(config config.Config) (app *App, err error) {
30-
entityManager, err := db.NewEntityManager(config.Database.Type, config.Database.Url)
31-
if err != nil {
32-
return
33+
func NewApp(config config.Config, migrateFlag bool) (app *App, err error) {
34+
var driver db.Driver
35+
switch config.Database.Type {
36+
case "mysql":
37+
driver = &mysql.MysqlDriver{}
38+
case "postgres":
39+
driver = &postgres.PostgresDriver{}
40+
case "":
41+
// Allow to start gateway server with a single endpoint: /payment
42+
break
43+
default:
44+
return nil, fmt.Errorf("%s database has no driver.", config.Database.Type)
3345
}
34-
repository, err := db.NewRepository(config.Database.Type, config.Database.Url)
35-
if err != nil {
36-
return
46+
47+
var entityManager db.EntityManagerInterface
48+
var repository db.RepositoryInterface
49+
50+
if driver != nil {
51+
err = driver.Init(config.Database.Url)
52+
if err != nil {
53+
return
54+
}
55+
56+
entityManager = db.NewEntityManager(driver)
57+
repository = db.NewRepository(driver)
3758
}
3859

39-
h := horizon.New(*config.Horizon)
60+
if migrateFlag {
61+
if driver == nil {
62+
log.Fatal("No database driver.")
63+
return
64+
}
65+
66+
var migrationsApplied int
67+
migrationsApplied, err = driver.MigrateUp()
68+
if err != nil {
69+
return
70+
}
4071

41-
if config.NetworkPassphrase == "" {
42-
config.NetworkPassphrase = "Test SDF Network ; September 2015"
72+
log.Info("Applied migrations: ", migrationsApplied)
73+
os.Exit(0)
74+
return
4375
}
4476

77+
h := horizon.New(*config.Horizon)
78+
4579
log.Print("Creating and initializing TransactionSubmitter")
46-
ts := submitter.NewTransactionSubmitter(&h, &entityManager, config.NetworkPassphrase)
80+
ts := submitter.NewTransactionSubmitter(&h, entityManager, config.NetworkPassphrase)
4781
if err != nil {
4882
return
4983
}
@@ -79,7 +113,7 @@ func NewApp(config config.Config) (app *App, err error) {
79113
log.Warning("No hooks.receive param. Skipping...")
80114
} else {
81115
var paymentListener listener.PaymentListener
82-
paymentListener, err = listener.NewPaymentListener(&config, &entityManager, &h, &repository, time.Now)
116+
paymentListener, err = listener.NewPaymentListener(&config, entityManager, &h, repository, time.Now)
83117
if err != nil {
84118
return
85119
}
@@ -98,9 +132,10 @@ func NewApp(config config.Config) (app *App, err error) {
98132

99133
app = &App{
100134
config: config,
101-
entityManager: &entityManager,
135+
driver: driver,
136+
entityManager: entityManager,
102137
horizon: &h,
103-
repository: &repository,
138+
repository: repository,
104139
transactionSubmitter: &ts,
105140
}
106141
return

src/github.com/stellar/gateway/cmd/gateway/main.go

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"github.com/spf13/viper"
99
"github.com/stellar/gateway"
1010
"github.com/stellar/gateway/config"
11-
"github.com/stellar/gateway/db/migrations"
1211
)
1312

1413
var app *gateway.App
@@ -35,18 +34,6 @@ func init() {
3534
rootCmd.Flags().BoolVarP(&migrateFlag, "migrate-db", "", false, "migrate DB to the newest schema version")
3635
}
3736

38-
func migrate(config config.Config) {
39-
migrationManager, err := migrations.NewMigrationManager(
40-
config.Database.Type,
41-
config.Database.Url,
42-
)
43-
if err != nil {
44-
log.Fatal("Error migrating DB")
45-
return
46-
}
47-
migrationManager.MigrateUp()
48-
}
49-
5037
func run(cmd *cobra.Command, args []string) {
5138
log.Print("Reading config.toml file")
5239
err := viper.ReadInConfig()
@@ -63,12 +50,7 @@ func run(cmd *cobra.Command, args []string) {
6350
return
6451
}
6552

66-
if migrateFlag {
67-
migrate(config)
68-
return
69-
}
70-
71-
app, err = gateway.NewApp(config)
53+
app, err = gateway.NewApp(config, migrateFlag)
7254

7355
if err != nil {
7456
log.Fatal(err.Error())
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package db
2+
3+
type Driver interface {
4+
Init(url string) (err error)
5+
MigrateUp() (migrationsApplied int, err error)
6+
7+
InsertReceivedPayment(object *ReceivedPayment) (id int64, err error)
8+
UpdateReceivedPayment(object *ReceivedPayment) (err error)
9+
GetLastReceivedPayment() (*ReceivedPayment, error)
10+
11+
InsertSentTransaction(object *SentTransaction) (id int64, err error)
12+
UpdateSentTransaction(object *SentTransaction) (err error)
13+
}

src/github.com/stellar/gateway/db/migrations/bindata.go renamed to src/github.com/stellar/gateway/db/drivers/mysql/bindata.go

Lines changed: 12 additions & 37 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package mysql
2+
3+
import (
4+
_ "github.com/go-sql-driver/mysql"
5+
"github.com/jmoiron/sqlx"
6+
"github.com/rubenv/sql-migrate"
7+
"github.com/stellar/gateway/db"
8+
)
9+
10+
type MysqlDriver struct {
11+
database *sqlx.DB
12+
}
13+
14+
func (d *MysqlDriver) Init(url string) (err error) {
15+
d.database, err = sqlx.Connect("mysql", url)
16+
return
17+
}
18+
19+
// go-bindata -ignore .+\.go$ -pkg mysql -o bindata.go ./migrations
20+
func (d *MysqlDriver) MigrateUp() (migrationsApplied int, err error) {
21+
source := d.getAssetMigrationSource()
22+
migrationsApplied, err = migrate.Exec(d.database.DB, "mysql", source, migrate.Up)
23+
return
24+
}
25+
26+
func (d *MysqlDriver) InsertReceivedPayment(object *db.ReceivedPayment) (id int64, err error) {
27+
query := `
28+
INSERT INTO ReceivedPayment
29+
(operation_id, processed_at, paging_token, status)
30+
VALUES
31+
(:operation_id, :processed_at, :paging_token, :status)`
32+
id, err = d.insert(query, object)
33+
return
34+
}
35+
36+
func (d *MysqlDriver) UpdateReceivedPayment(object *db.ReceivedPayment) (err error) {
37+
query := `
38+
UPDATE ReceivedPayment SET
39+
operation_id = :operation_id,
40+
processed_at = :processed_at,
41+
paging_token = :paging_token,
42+
status = :status
43+
WHERE
44+
id = :id`
45+
err = d.update(query, object)
46+
return
47+
}
48+
49+
func (d *MysqlDriver) GetLastReceivedPayment() (*db.ReceivedPayment, error) {
50+
var receivedPayment db.ReceivedPayment
51+
err := d.database.Get(&receivedPayment, "SELECT * FROM ReceivedPayment ORDER BY id DESC LIMIT 1")
52+
if err != nil {
53+
if err.Error() == "sql: no rows in result set" {
54+
return nil, nil
55+
} else {
56+
return nil, err
57+
}
58+
}
59+
return &receivedPayment, nil
60+
}
61+
62+
func (d *MysqlDriver) InsertSentTransaction(object *db.SentTransaction) (id int64, err error) {
63+
query := `
64+
INSERT INTO SentTransaction
65+
(status, source, submitted_at, succeeded_at, ledger, envelope_xdr, result_xdr)
66+
VALUES
67+
(:status, :source, :submitted_at, :succeeded_at, :ledger, :envelope_xdr, :result_xdr)`
68+
id, err = d.insert(query, object)
69+
return
70+
}
71+
72+
func (d *MysqlDriver) UpdateSentTransaction(object *db.SentTransaction) (err error) {
73+
query := `
74+
UPDATE SentTransaction SET
75+
status = :status,
76+
source = :source,
77+
submitted_at = :submitted_at,
78+
succeeded_at = :succeeded_at,
79+
ledger = :ledger,
80+
envelope_xdr = :envelope_xdr,
81+
result_xdr = :result_xdr
82+
WHERE
83+
id = :id`
84+
err = d.update(query, object)
85+
return
86+
}
87+
88+
func (d *MysqlDriver) insert(query string, object interface{}) (id int64, err error) {
89+
result, err := d.database.NamedExec(query, object)
90+
if err != nil {
91+
return
92+
}
93+
94+
id, err = result.LastInsertId()
95+
return
96+
}
97+
98+
func (d *MysqlDriver) update(query string, object interface{}) (err error) {
99+
_, err = d.database.NamedExec(query, object)
100+
return
101+
}
102+
103+
func (d *MysqlDriver) getAssetMigrationSource() (source *migrate.AssetMigrationSource) {
104+
source = &migrate.AssetMigrationSource{
105+
Asset: Asset,
106+
AssetDir: AssetDir,
107+
Dir: "migrations",
108+
}
109+
return
110+
}

0 commit comments

Comments
 (0)