Skip to content

Commit 984d03d

Browse files
author
Mikhail Podtserkovskiy
committed
- мок селениума
- выбор реализации сторожа из кончика - фиксы дедлоков - улучшение описания ошибок
1 parent 1ff68cb commit 984d03d

File tree

11 files changed

+374
-59
lines changed

11 files changed

+374
-59
lines changed

config-sample.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"level": 6
44
},
55
"db": {
6+
"implementation": "mysql",
67
"connection": "root:@(localhost:3306)/grid?tx_isolation=SERIALIZABLE&parseTime=true"
78
},
89
"grid": {

config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type Logger struct {
3232
}
3333

3434
type DB struct {
35+
Implementation string `json:"implementation"`
3536
Connection string `json:"connection"`
3637
}
3738

handlers/createSession.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func (h *CreateSession) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
2525
http.Error(rw, "Method Not Allowed", http.StatusMethodNotAllowed)
2626
return
2727
}
28-
var capabilities map[string]Capabilities
28+
var capabilities map[string]jsonwire.Capabilities
2929
body, err := ioutil.ReadAll(r.Body)
3030
if err != nil {
3131
errorMessage := "Error reading request: " + err.Error()
@@ -80,7 +80,7 @@ func (h *CreateSession) tryCreateSession(r *http.Request, capabilities *pool.Cap
8080
seleniumNode := jsonwire.NewNode(seleniumClient)
8181
_, err = seleniumNode.RemoveAllSessions()
8282
if err != nil {
83-
log.Warn("Can't remove all sessions from node, go to next available node: " + node.String())
83+
log.Warn("Can't remove all sessions from node: " + err.Error() + ", go to next available node: " + node.String())
8484
h.Pool.Remove(node)
8585
return h.tryCreateSession(r, capabilities)
8686
}

handlers/registerNode.go

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,13 @@ import (
88

99
log "github.com/Sirupsen/logrus"
1010
"github.com/qa-dev/jsonwire-grid/pool"
11+
"github.com/qa-dev/jsonwire-grid/jsonwire"
1112
)
1213

1314
type RegisterNode struct {
1415
Pool *pool.Pool
1516
}
1617

17-
type registerJson struct {
18-
Class string `json:"class"`
19-
Configuration *configurationJson `json:"configuration"`
20-
CapabilitiesList []Capabilities `json:"capabilities"` // selenium 3
21-
}
22-
23-
type Capabilities map[string]interface{}
24-
25-
type configurationJson struct {
26-
Proxy string
27-
Role string
28-
Hub string
29-
Port int
30-
RemoteHost string
31-
Host string
32-
MaxSession int
33-
HubHost string
34-
RegisterCycle int
35-
HubPort int
36-
Url string
37-
Register bool
38-
CapabilitiesList []Capabilities `json:"capabilities"` // selenium 2
39-
}
40-
4118
func (h *RegisterNode) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
4219
body, err := ioutil.ReadAll(r.Body)
4320
if err != nil {
@@ -47,7 +24,7 @@ func (h *RegisterNode) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
4724
return
4825
}
4926
r.Body.Close()
50-
var register registerJson
27+
var register jsonwire.Register
5128
err = json.Unmarshal(body, &register)
5229
if err != nil {
5330
errorMessage := "Can't unmarshal register json: " + err.Error()
@@ -56,7 +33,7 @@ func (h *RegisterNode) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
5633
return
5734
}
5835

59-
var capabilitiesList []Capabilities
36+
var capabilitiesList []jsonwire.Capabilities
6037

6138
//todo: знаю что костыль, переделаю
6239
if len(register.Configuration.CapabilitiesList) > 0 {

handlers/useSession.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func (h *UseSession) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
2020
if len(parsedUrl) != 3 {
2121
errorMessage := "url [" + r.URL.Path + "] parsing error"
2222
log.Infof(errorMessage)
23-
http.Error(rw, errorMessage, http.StatusInternalServerError)
23+
http.Error(rw, errorMessage, http.StatusBadRequest)
2424
return
2525
}
2626
sessionId := re.FindStringSubmatch(r.URL.Path)[1]
@@ -33,7 +33,7 @@ func (h *UseSession) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
3333
// посылаем сообщение о том что сессия не найдена
3434
errorMessage = "session " + sessionId + " not found in node pool: " + errorMessage
3535
log.Infof(errorMessage)
36-
http.Error(rw, errorMessage, http.StatusInternalServerError)
36+
http.Error(rw, errorMessage, http.StatusNotFound)
3737
return
3838
}
3939

invoke.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package main
2+
3+
import (
4+
log "github.com/Sirupsen/logrus"
5+
_ "github.com/go-sql-driver/mysql"
6+
"github.com/jmoiron/sqlx"
7+
"github.com/qa-dev/jsonwire-grid/config"
8+
"github.com/qa-dev/jsonwire-grid/pool"
9+
10+
"errors"
11+
mysqlMigrations "github.com/qa-dev/jsonwire-grid/storage/migrations/mysql"
12+
"github.com/qa-dev/jsonwire-grid/storage/mysql"
13+
"github.com/rubenv/sql-migrate"
14+
)
15+
16+
func invokeStorage(config config.Config) (storage pool.StorageInterface, err error) {
17+
switch config.DB.Implementation {
18+
case "mysql":
19+
var db *sqlx.DB
20+
db, err = sqlx.Open("mysql", config.DB.Connection)
21+
if err != nil {
22+
err = errors.New("Database connection error: " + err.Error())
23+
return
24+
}
25+
26+
storage = mysql.NewMysqlStorage(db)
27+
28+
migrations := &migrate.AssetMigrationSource{
29+
Asset: mysqlMigrations.Asset,
30+
AssetDir: mysqlMigrations.AssetDir,
31+
Dir: "storage/migrations/mysql",
32+
}
33+
var n int
34+
n, err = migrate.Exec(db.DB, "mysql", migrations, migrate.Up)
35+
if err != nil {
36+
err = errors.New("Migrations failed, " + err.Error())
37+
return
38+
}
39+
log.Infof("Applied %d migrations!\n", n)
40+
default:
41+
err = errors.New("Invalid config, unknown param [DB.Implementation=" + config.DB.Implementation + "]")
42+
}
43+
return
44+
}

jsonwire/jsonwire.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
type Message struct {
88
SessionId string `json:"sessionId"`
99
Status int `json:"status"`
10-
Value []interface{} `json:"value"`
10+
Value interface{} `json:"value"`
1111
}
1212

1313
type NewSession struct {
@@ -24,3 +24,34 @@ type Sessions struct {
2424
Capabilities json.RawMessage `json:"capabilities"`
2525
} `json:"value"`
2626
}
27+
28+
type Register struct {
29+
Class string `json:"class"`
30+
Configuration *Configuration `json:"configuration"`
31+
CapabilitiesList []Capabilities `json:"capabilities"` // selenium 3
32+
}
33+
34+
type Capabilities map[string]interface{}
35+
36+
type Configuration struct {
37+
Proxy string
38+
Role string
39+
Hub string
40+
Port int
41+
RemoteHost string
42+
Host string
43+
MaxSession int
44+
HubHost string
45+
RegisterCycle int
46+
HubPort int
47+
Url string
48+
Register bool
49+
CapabilitiesList []Capabilities `json:"capabilities"` // selenium 2
50+
}
51+
52+
type ApiProxy struct {
53+
ID string `json:"id"`
54+
Request interface{} `json:"request"` //todo: пока не ясно зачем он нужен
55+
Msg string `json:"msg"`
56+
Success bool `json:"success"`
57+
}

main.go

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,13 @@ import (
44
"context"
55
"fmt"
66
log "github.com/Sirupsen/logrus"
7-
_ "github.com/go-sql-driver/mysql"
8-
"github.com/jmoiron/sqlx"
97
"github.com/qa-dev/jsonwire-grid/config"
108
"github.com/qa-dev/jsonwire-grid/handlers"
119
"github.com/qa-dev/jsonwire-grid/logger"
1210
"github.com/qa-dev/jsonwire-grid/middleware"
1311
"github.com/qa-dev/jsonwire-grid/pool"
1412
poolMetrics "github.com/qa-dev/jsonwire-grid/pool/metrics"
15-
mysqlMigrations "github.com/qa-dev/jsonwire-grid/storage/migrations/mysql"
16-
"github.com/qa-dev/jsonwire-grid/storage/mysql"
1713
"github.com/qa-dev/jsonwire-grid/utils/metrics"
18-
"github.com/rubenv/sql-migrate"
1914
"net/http"
2015
"os"
2116
"os/signal"
@@ -29,27 +24,10 @@ func main() {
2924
cfg := config.New()
3025
err := cfg.LoadFromFile(os.Getenv("CONFIG_PATH"))
3126
if err != nil {
32-
log.Fatalf("Problem in loading config from file, %s", err.Error())
27+
log.Fatalf("Problem in loading config from file, %s", err)
3328
}
3429
logger.Init(cfg.Logger)
3530

36-
db, err := sqlx.Open("mysql", cfg.DB.Connection)
37-
if err != nil {
38-
log.Fatalf("Database connection error: %s", err.Error())
39-
}
40-
storage := mysql.NewMysqlStorage(db)
41-
42-
migrations := &migrate.AssetMigrationSource{
43-
Asset: mysqlMigrations.Asset,
44-
AssetDir: mysqlMigrations.AssetDir,
45-
Dir: "storage/migrations/mysql",
46-
}
47-
n, err := migrate.Exec(db.DB, "mysql", migrations, migrate.Up)
48-
if err != nil {
49-
log.Fatalf("Migrations failed, %s", err.Error())
50-
}
51-
fmt.Printf("Applied %d migrations!\n", n)
52-
5331
statsdClient, err := metrics.NewStatsd(
5432
cfg.Statsd.Host,
5533
cfg.Statsd.Port,
@@ -58,13 +36,17 @@ func main() {
5836
cfg.Statsd.Enable)
5937

6038
if nil != err {
61-
log.Errorf("Statsd create socked error: %s", err.Error())
39+
log.Errorf("Statsd create socked error: %s", err)
6240
}
6341

6442
busyNodeDuration, err := time.ParseDuration(cfg.Grid.BusyNodeDuration)
6543
reservedNodeDuration, err := time.ParseDuration(cfg.Grid.BusyNodeDuration)
6644
if err != nil {
67-
panic("Invalid value grid.busy_node_duration in config")
45+
log.Fatal("Invalid value grid.busy_node_duration in config")
46+
}
47+
storage, err := invokeStorage(*cfg)
48+
if err != nil {
49+
log.Fatalf("Can't invoke storage, %s", err)
6850
}
6951
poolInstance := pool.NewPool(storage)
7052
poolInstance.SetBusyNodeDuration(busyNodeDuration)
@@ -94,7 +76,7 @@ func main() {
9476
err = server.ListenAndServe()
9577
if err != nil {
9678
// todo: норма ли что при закрытии всегда возвращается еррор???
97-
log.Errorf("Listen serve error, %s", err.Error())
79+
log.Errorf("Listen serve error, %s", err)
9880
}
9981
}()
10082

selenium/client.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net/http"
88
"net/url"
99
"strings"
10+
"errors"
1011
)
1112

1213
type Client struct {
@@ -39,10 +40,15 @@ func (c *Client) Sessions() (*jsonwire.Sessions, error) {
3940
}
4041
request, err := newRequest(http.MethodGet, reqUrl.String(), "")
4142
if err != nil {
43+
err = errors.New("Cant create request, " + err.Error())
4244
return nil, err
4345
}
4446
var sessions jsonwire.Sessions
4547
err = request.send(&sessions)
48+
if err != nil {
49+
err = errors.New("Cant read response, " + err.Error())
50+
return nil, err
51+
}
4652
return &sessions, err
4753
}
4854

@@ -54,10 +60,15 @@ func (c *Client) CloseSession(sessionId string) (*jsonwire.Message, error) {
5460
}
5561
request, err := newRequest(http.MethodDelete, reqUrl.String(), "")
5662
if err != nil {
63+
err = errors.New("Cant create request, " + err.Error())
5764
return nil, err
5865
}
5966
var message jsonwire.Message
6067
err = request.send(&message)
68+
if err != nil {
69+
err = errors.New("Cant send response, " + err.Error())
70+
return nil, err
71+
}
6172
return &message, err
6273
}
6374

@@ -79,16 +90,19 @@ func newRequest(method, url string, requestBodyContent string) (*request, error)
7990
func (req request) send(outputStruct interface{}) error {
8091
resp, err := http.DefaultClient.Do(req.httpRequest)
8192
if err != nil {
93+
err = errors.New("can't send request, " + err.Error())
8294
return err
8395
}
8496
defer resp.Body.Close()
8597
// todo: Получение респонза и разбор пока здесь.
8698
body, err := ioutil.ReadAll(resp.Body)
8799
if err != nil {
100+
err = errors.New("can't read response body, " + err.Error())
88101
return err
89102
}
90103
err = json.Unmarshal(body, outputStruct)
91104
if err != nil {
105+
err = errors.New("can't unmarshal response ["+ string(body)+"], " + err.Error())
92106
return err
93107
}
94108
return nil

storage/mysql/storage.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,15 @@ func (s *MysqlStorage) ReserveAvailable(capabilities pool.Capabilities) (node po
155155
WHERE `+where+`
156156
GROUP BY c.setId
157157
HAVING count(c.setId) = `+countCapabilities+`
158-
ORDER BY n.updated ASC
158+
ORDER BY n.updated DESC
159159
LIMIT 1
160160
FOR UPDATE
161161
`,
162162
args...).
163163
StructScan(nodeModel)
164164
default:
165165
err = tx.QueryRowx(
166-
`SELECT n.* FROM node n WHERE `+where+` ORDER BY n.updated ASC LIMIT 1 FOR UPDATE`,
166+
`SELECT n.* FROM node n WHERE `+where+` ORDER BY n.updated DESC LIMIT 1 FOR UPDATE`,
167167
args...).
168168
StructScan(nodeModel)
169169
}

0 commit comments

Comments
 (0)