1
0
mirror of https://github.com/mattermost/focalboard.git synced 2024-11-24 08:22:29 +02:00

Some other code improvements from the golangci

This commit is contained in:
Jesús Espino 2020-10-22 15:22:36 +02:00
parent 607b8aa063
commit 72f4783e34
17 changed files with 177 additions and 83 deletions

View File

@ -51,15 +51,18 @@ func (a *API) handleGetBlocks(w http.ResponseWriter, r *http.Request) {
blocks, err := a.app().GetBlocks(parentID, blockType)
if err != nil {
log.Printf(`ERROR GetBlocks: %v`, r)
errorResponse(w, http.StatusInternalServerError, `{}`)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
log.Printf("GetBlocks parentID: %s, type: %s, %d result(s)", parentID, blockType, len(blocks))
json, err := json.Marshal(blocks)
if err != nil {
log.Printf(`ERROR json.Marshal: %v`, r)
errorResponse(w, http.StatusInternalServerError, `{}`)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
@ -69,7 +72,8 @@ func (a *API) handleGetBlocks(w http.ResponseWriter, r *http.Request) {
func (a *API) handlePostBlocks(w http.ResponseWriter, r *http.Request) {
requestBody, err := ioutil.ReadAll(r.Body)
if err != nil {
errorResponse(w, http.StatusInternalServerError, `{}`)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
@ -77,32 +81,41 @@ func (a *API) handlePostBlocks(w http.ResponseWriter, r *http.Request) {
defer func() {
if r := recover(); r != nil {
log.Printf(`ERROR: %v`, r)
errorResponse(w, http.StatusInternalServerError, `{}`)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
}()
var blocks []model.Block
err = json.Unmarshal(requestBody, &blocks)
if err != nil {
errorResponse(w, http.StatusInternalServerError, ``)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
for _, block := range blocks {
// Error checking
if len(block.Type) < 1 {
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf(`{"description": "missing type", "id": "%s"}`, block.ID))
errorData := map[string]string{"description": "missing type", "id": block.ID}
errorResponse(w, http.StatusBadRequest, errorData)
return
}
if block.CreateAt < 1 {
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf(`{"description": "invalid createAt", "id": "%s"}`, block.ID))
errorData := map[string]string{"description": "invalid createAt", "id": block.ID}
errorResponse(w, http.StatusBadRequest, errorData)
return
}
if block.UpdateAt < 1 {
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf(`{"description": "invalid updateAt", "id": "%s"}`, block.ID))
errorData := map[string]string{"description": "invalid UpdateAt", "id": block.ID}
errorResponse(w, http.StatusBadRequest, errorData)
return
}
}
@ -110,7 +123,8 @@ func (a *API) handlePostBlocks(w http.ResponseWriter, r *http.Request) {
err = a.app().InsertBlocks(blocks)
if err != nil {
log.Printf(`ERROR: %v`, r)
errorResponse(w, http.StatusInternalServerError, `{}`)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
@ -125,7 +139,8 @@ func (a *API) handleDeleteBlock(w http.ResponseWriter, r *http.Request) {
err := a.app().DeleteBlock(blockID)
if err != nil {
log.Printf(`ERROR: %v`, r)
errorResponse(w, http.StatusInternalServerError, `{}`)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
@ -140,7 +155,8 @@ func (a *API) handleGetSubTree(w http.ResponseWriter, r *http.Request) {
blocks, err := a.app().GetSubTree(blockID)
if err != nil {
log.Printf(`ERROR: %v`, r)
errorResponse(w, http.StatusInternalServerError, `{}`)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
@ -148,7 +164,8 @@ func (a *API) handleGetSubTree(w http.ResponseWriter, r *http.Request) {
json, err := json.Marshal(blocks)
if err != nil {
log.Printf(`ERROR json.Marshal: %v`, r)
errorResponse(w, http.StatusInternalServerError, `{}`)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
@ -159,15 +176,18 @@ func (a *API) handleExport(w http.ResponseWriter, r *http.Request) {
blocks, err := a.app().GetAllBlocks()
if err != nil {
log.Printf(`ERROR: %v`, r)
errorResponse(w, http.StatusInternalServerError, `{}`)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
log.Printf("EXPORT Blocks, %d result(s)", len(blocks))
json, err := json.Marshal(blocks)
if err != nil {
log.Printf(`ERROR json.Marshal: %v`, r)
errorResponse(w, http.StatusInternalServerError, `{}`)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
@ -177,7 +197,8 @@ func (a *API) handleExport(w http.ResponseWriter, r *http.Request) {
func (a *API) handleImport(w http.ResponseWriter, r *http.Request) {
requestBody, err := ioutil.ReadAll(r.Body)
if err != nil {
errorResponse(w, http.StatusInternalServerError, `{}`)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
@ -185,15 +206,18 @@ func (a *API) handleImport(w http.ResponseWriter, r *http.Request) {
defer func() {
if r := recover(); r != nil {
log.Printf(`ERROR: %v`, r)
errorResponse(w, http.StatusInternalServerError, `{}`)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
}()
var blocks []model.Block
err = json.Unmarshal(requestBody, &blocks)
if err != nil {
errorResponse(w, http.StatusInternalServerError, ``)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
@ -201,7 +225,8 @@ func (a *API) handleImport(w http.ResponseWriter, r *http.Request) {
err := a.app().InsertBlock(block)
if err != nil {
log.Printf(`ERROR: %v`, r)
errorResponse(w, http.StatusInternalServerError, `{}`)
errorResponse(w, http.StatusInternalServerError, nil)
return
}
}
@ -217,6 +242,7 @@ func (a *API) handleServeFile(w http.ResponseWriter, r *http.Request) {
filename := vars["filename"]
contentType := "image/jpg"
fileExtension := strings.ToLower(filepath.Ext(filename))
if fileExtension == "png" {
contentType = "image/png"
@ -234,6 +260,7 @@ func (a *API) handleUploadFile(w http.ResponseWriter, r *http.Request) {
file, handle, err := r.FormFile("file")
if err != nil {
fmt.Fprintf(w, "%v", err)
return
}
defer file.Close()
@ -243,6 +270,7 @@ func (a *API) handleUploadFile(w http.ResponseWriter, r *http.Request) {
url, err := a.app().SaveFile(file, handle.Filename)
if err != nil {
jsonStringResponse(w, http.StatusInternalServerError, `{}`)
return
}
@ -265,10 +293,14 @@ func jsonBytesResponse(w http.ResponseWriter, code int, json []byte) {
w.Write(json)
}
func errorResponse(w http.ResponseWriter, code int, message string) {
func errorResponse(w http.ResponseWriter, code int, message map[string]string) {
log.Printf("%d ERROR", code)
data, err := json.Marshal(message)
if err != nil {
data = []byte("{}")
}
w.WriteHeader(code)
fmt.Fprint(w, message)
fmt.Fprint(w, data)
}
func addUserID(rw http.ResponseWriter, req *http.Request, next http.Handler) {

View File

@ -8,9 +8,11 @@ func (a *App) GetBlocks(parentID string, blockType string) ([]model.Block, error
if len(blockType) > 0 && len(parentID) > 0 {
return a.store.GetBlocksWithParentAndType(parentID, blockType)
}
if len(blockType) > 0 {
return a.store.GetBlocksWithType(blockType)
}
return a.store.GetBlocksWithParent(parentID)
}
@ -23,7 +25,7 @@ func (a *App) InsertBlock(block model.Block) error {
}
func (a *App) InsertBlocks(blocks []model.Block) error {
var blockIDsToNotify = []string{}
blockIDsToNotify := []string{}
uniqueBlockIDs := make(map[string]bool)
@ -43,6 +45,7 @@ func (a *App) InsertBlocks(blocks []model.Block) error {
}
a.wsServer.BroadcastBlockChangeToWebsocketClients(blockIDsToNotify)
return nil
}
@ -55,7 +58,7 @@ func (a *App) GetAllBlocks() ([]model.Block, error) {
}
func (a *App) DeleteBlock(blockID string) error {
var blockIDsToNotify = []string{blockID}
blockIDsToNotify := []string{blockID}
parentID, err := a.GetParentID(blockID)
if err != nil {
return err
@ -71,5 +74,6 @@ func (a *App) DeleteBlock(blockID string) error {
}
a.wsServer.BroadcastBlockChangeToWebsocketClients(blockIDsToNotify)
return nil
}

View File

@ -32,5 +32,4 @@ func TestGetParentID(t *testing.T) {
require.Error(t, err)
require.Equal(t, "block-not-found", err.Error())
})
}

View File

@ -23,23 +23,24 @@ func (a *App) SaveFile(reader io.Reader, filename string) (string, error) {
if appErr != nil {
return "", errors.New("unable to store the file in the files storage")
}
return fmt.Sprintf(`%s/files/%s`, a.config.ServerRoot, createdFilename), nil
}
func (a *App) GetFilePath(filename string) string {
folderPath := a.config.FilesPath
return filepath.Join(folderPath, filename)
}
// CreateGUID returns a random GUID
// CreateGUID returns a random GUID.
func createGUID() string {
b := make([]byte, 16)
_, err := rand.Read(b)
if err != nil {
log.Fatal(err)
}
uuid := fmt.Sprintf("%x-%x-%x-%x-%x",
b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
uuid := fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
return uuid
}

View File

@ -2,11 +2,10 @@ package main
import (
"flag"
"syscall"
"time"
"log"
"os"
"syscall"
"time"
"github.com/mattermost/mattermost-octo-tasks/server/server"
"github.com/mattermost/mattermost-octo-tasks/server/services/config"
@ -26,6 +25,7 @@ func isProcessRunning(pid int) bool {
}
err = process.Signal(syscall.Signal(0))
return err == nil
}
@ -49,6 +49,7 @@ func main() {
config, err := config.ReadConfigFile()
if err != nil {
log.Fatal("Unable to read the config file: ", err)
return
}

View File

@ -1,6 +1,6 @@
package model
// Block is the basic data unit
// Block is the basic data unit.
type Block struct {
ID string `json:"id"`
ParentID string `json:"parentId"`

View File

@ -22,12 +22,12 @@ import (
"github.com/mattermost/mattermost-server/v5/services/filesstore"
)
const CurrentVersion = "0.0.1"
const currentVersion = "0.0.1"
type Server struct {
config *config.Configuration
wsServer *ws.Server
webServer *web.WebServer
webServer *web.Server
store store.Store
filesBackend filesstore.FileBackend
telemetry *telemetry.Service
@ -43,6 +43,7 @@ func New(cfg *config.Configuration) (*Server, error) {
store, err := sqlstore.New(cfg.DBType, cfg.DBConfigString)
if err != nil {
log.Fatal("Unable to start the database", err)
return nil, err
}
@ -54,13 +55,14 @@ func New(cfg *config.Configuration) (*Server, error) {
filesBackend, appErr := filesstore.NewFileBackend(&filesBackendSettings, false)
if appErr != nil {
log.Fatal("Unable to initialize the files storage")
return nil, errors.New("unable to initialize the files storage")
}
appBuilder := func() *app.App { return app.New(cfg, store, wsServer, filesBackend) }
webServer := web.NewWebServer(cfg.WebPath, cfg.Port, cfg.UseSSL)
api := api.NewAPI(appBuilder)
webServer := web.NewServer(cfg.WebPath, cfg.Port, cfg.UseSSL)
webServer.AddRoutes(wsServer)
webServer.AddRoutes(api)
@ -95,7 +97,22 @@ func New(cfg *config.Configuration) (*Server, error) {
}
telemetryService := telemetry.New(telemetryID, zap.NewStdLog(logger))
srv := &Server{
telemetryService.RegisterTracker("server", func() map[string]interface{} {
return map[string]interface{}{
"version": currentVersion,
"operating_system": runtime.GOOS,
}
})
telemetryService.RegisterTracker("config", func() map[string]interface{} {
return map[string]interface{}{
"serverRoot": cfg.ServerRoot == config.DefaultServerRoot,
"port": cfg.Port == config.DefaultPort,
"useSSL": cfg.UseSSL,
"dbType": cfg.DBType,
}
})
return &Server{
config: cfg,
wsServer: wsServer,
webServer: webServer,
@ -103,29 +120,14 @@ func New(cfg *config.Configuration) (*Server, error) {
filesBackend: filesBackend,
telemetry: telemetryService,
logger: logger,
}
telemetryService.RegisterTracker("server", func() map[string]interface{} {
return map[string]interface{}{
"version": CurrentVersion,
"operating_system": runtime.GOOS,
}
})
telemetryService.RegisterTracker("config", func() map[string]interface{} {
return map[string]interface{}{
"serverRoot": srv.config.ServerRoot == config.DefaultServerRoot,
"port": srv.config.Port == config.DefaultPort,
"useSSL": srv.config.UseSSL,
"dbType": srv.config.DBType,
}
})
return srv, nil
}, nil
}
func (s *Server) Start() error {
if err := s.webServer.Start(); err != nil {
return err
}
return nil
}

View File

@ -11,7 +11,7 @@ const (
DefaultPort = 8000
)
// Configuration is the app configuration stored in a json file
// Configuration is the app configuration stored in a json file.
type Configuration struct {
ServerRoot string `json:"serverRoot" mapstructure:"serverRoot"`
Port int `json:"port" mapstructure:"port"`
@ -23,6 +23,7 @@ type Configuration struct {
Telemetry bool `json:"telemetry" mapstructure:"telemetry"`
}
// ReadConfigFile read the configuration from the filesystem.
func ReadConfigFile() (*Configuration, error) {
viper.SetConfigName("config") // name of config file (without extension)
viper.SetConfigType("json") // REQUIRED if the config file does not have the extension in the name
@ -40,6 +41,7 @@ func ReadConfigFile() (*Configuration, error) {
}
configuration := Configuration{}
err = viper.Unmarshal(&configuration)
if err != nil {
return nil, err

View File

@ -22,6 +22,7 @@ func TestCreateTask(t *testing.T) {
}
task := CreateTask(taskName, testFunc, taskTime)
assert.EqualValues(t, 0, atomic.LoadInt32(executionCount))
time.Sleep(taskTime + taskWait)
@ -43,6 +44,7 @@ func TestCreateRecurringTask(t *testing.T) {
}
task := CreateRecurringTask(taskName, testFunc, taskTime)
assert.EqualValues(t, 0, atomic.LoadInt32(executionCount))
time.Sleep(taskTime + taskWait)
@ -70,6 +72,7 @@ func TestCancelTask(t *testing.T) {
}
task := CreateTask(taskName, testFunc, taskTime)
assert.EqualValues(t, 0, atomic.LoadInt32(executionCount))
task.Cancel()

View File

@ -13,16 +13,21 @@ import (
)
func (s *SQLStore) latestsBlocksSubquery() sq.SelectBuilder {
return sq.Select("*").FromSelect(sq.Select("*", "ROW_NUMBER() OVER (PARTITION BY id ORDER BY insert_at DESC) AS rn").From("blocks"), "a").Where(sq.Eq{"rn": 1})
internalQuery := sq.Select("*", "ROW_NUMBER() OVER (PARTITION BY id ORDER BY insert_at DESC) AS rn").From("blocks")
return sq.Select("*").FromSelect(internalQuery, "a").Where(sq.Eq{"rn": 1})
}
func (s *SQLStore) GetBlocksWithParentAndType(parentID string, blockType string) ([]model.Block, error) {
query := s.getQueryBuilder().
Select("id", "parent_id", "schema", "type", "title", "COALESCE(\"fields\", '{}')", "create_at", "update_at", "delete_at").
Select("id", "parent_id", "schema", "type", "title",
"COALESCE(\"fields\", '{}')", "create_at", "update_at",
"delete_at").
FromSelect(s.latestsBlocksSubquery(), "latest").
Where(sq.Eq{"delete_at": 0}).
Where(sq.Eq{"parent_id": parentID}).
Where(sq.Eq{"type": blockType})
rows, err := query.Query()
if err != nil {
log.Printf(`getBlocksWithParentAndType ERROR: %v`, err)
@ -35,7 +40,9 @@ func (s *SQLStore) GetBlocksWithParentAndType(parentID string, blockType string)
func (s *SQLStore) GetBlocksWithParent(parentID string) ([]model.Block, error) {
query := s.getQueryBuilder().
Select("id", "parent_id", "schema", "type", "title", "COALESCE(\"fields\", '{}')", "create_at", "update_at", "delete_at").
Select("id", "parent_id", "schema", "type", "title",
"COALESCE(\"fields\", '{}')", "create_at", "update_at",
"delete_at").
FromSelect(s.latestsBlocksSubquery(), "latest").
Where(sq.Eq{"delete_at": 0}).
Where(sq.Eq{"parent_id": parentID})
@ -43,6 +50,7 @@ func (s *SQLStore) GetBlocksWithParent(parentID string) ([]model.Block, error) {
rows, err := query.Query()
if err != nil {
log.Printf(`getBlocksWithParent ERROR: %v`, err)
return nil, err
}
@ -51,13 +59,17 @@ func (s *SQLStore) GetBlocksWithParent(parentID string) ([]model.Block, error) {
func (s *SQLStore) GetBlocksWithType(blockType string) ([]model.Block, error) {
query := s.getQueryBuilder().
Select("id", "parent_id", "schema", "type", "title", "COALESCE(\"fields\", '{}')", "create_at", "update_at", "delete_at").
Select("id", "parent_id", "schema", "type", "title",
"COALESCE(\"fields\", '{}')", "create_at", "update_at",
"delete_at").
FromSelect(s.latestsBlocksSubquery(), "latest").
Where(sq.Eq{"delete_at": 0}).
Where(sq.Eq{"type": blockType})
rows, err := query.Query()
if err != nil {
log.Printf(`getBlocksWithParentAndType ERROR: %v`, err)
return nil, err
}
@ -66,7 +78,9 @@ func (s *SQLStore) GetBlocksWithType(blockType string) ([]model.Block, error) {
func (s *SQLStore) GetSubTree(blockID string) ([]model.Block, error) {
query := s.getQueryBuilder().
Select("id", "parent_id", "schema", "type", "title", "COALESCE(\"fields\", '{}')", "create_at", "update_at", "delete_at").
Select("id", "parent_id", "schema", "type", "title",
"COALESCE(\"fields\", '{}')", "create_at", "update_at",
"delete_at").
FromSelect(s.latestsBlocksSubquery(), "latest").
Where(sq.Eq{"delete_at": 0}).
Where(sq.Or{sq.Eq{"id": blockID}, sq.Eq{"parent_id": blockID}})
@ -74,6 +88,7 @@ func (s *SQLStore) GetSubTree(blockID string) ([]model.Block, error) {
rows, err := query.Query()
if err != nil {
log.Printf(`getSubTree ERROR: %v`, err)
return nil, err
}
@ -82,13 +97,16 @@ func (s *SQLStore) GetSubTree(blockID string) ([]model.Block, error) {
func (s *SQLStore) GetAllBlocks() ([]model.Block, error) {
query := s.getQueryBuilder().
Select("id", "parent_id", "schema", "type", "title", "COALESCE(\"fields\", '{}')", "create_at", "update_at", "delete_at").
Select("id", "parent_id", "schema", "type", "title",
"COALESCE(\"fields\", '{}')", "create_at", "update_at",
"delete_at").
FromSelect(s.latestsBlocksSubquery(), "latest").
Where(sq.Eq{"delete_at": 0})
rows, err := query.Query()
if err != nil {
log.Printf(`getAllBlocks ERROR: %v`, err)
return nil, err
}
@ -117,6 +135,7 @@ func blocksFromRows(rows *sql.Rows) ([]model.Block, error) {
if err != nil {
// handle this error
log.Printf(`ERROR blocksFromRows: %v`, err)
return nil, err
}
@ -124,6 +143,7 @@ func blocksFromRows(rows *sql.Rows) ([]model.Block, error) {
if err != nil {
// handle this error
log.Printf(`ERROR blocksFromRows fields: %v`, err)
return nil, err
}
@ -142,6 +162,7 @@ func (s *SQLStore) GetParentID(blockID string) (string, error) {
row := query.QueryRow()
var parentID string
err := row.Scan(&parentID)
if err != nil {
return "", err
@ -158,20 +179,25 @@ func (s *SQLStore) InsertBlock(block model.Block) error {
query := s.getQueryBuilder().Insert("blocks").
Columns("id", "parent_id", "schema", "type", "title", "fields", "create_at", "update_at", "delete_at").
Values(block.ID, block.ParentID, block.Schema, block.Type, block.Title, fieldsJSON, block.CreateAt, block.UpdateAt, block.DeleteAt)
Values(block.ID, block.ParentID, block.Schema, block.Type, block.Title,
fieldsJSON, block.CreateAt, block.UpdateAt, block.DeleteAt)
_, err = query.Exec()
if err != nil {
return err
}
return nil
}
func (s *SQLStore) DeleteBlock(blockID string) error {
now := time.Now().Unix()
query := s.getQueryBuilder().Insert("blocks").Columns("id", "update_at", "delete_at").Values(blockID, now, now)
_, err := query.Exec()
if err != nil {
return err
}
return nil
}

View File

@ -7,13 +7,13 @@ import (
sq "github.com/Masterminds/squirrel"
)
// SQLStore is a SQL database
// SQLStore is a SQL database.
type SQLStore struct {
db *sql.DB
dbType string
}
// New creates a new SQL implementation of the store
// New creates a new SQL implementation of the store.
func New(dbType, connectionString string) (*SQLStore, error) {
log.Println("connectDatabase")
var err error
@ -21,12 +21,14 @@ func New(dbType, connectionString string) (*SQLStore, error) {
db, err := sql.Open(dbType, connectionString)
if err != nil {
log.Fatal("connectDatabase: ", err)
return nil, err
}
err = db.Ping()
if err != nil {
log.Println(`Database Ping failed`)
return nil, err
}
@ -38,16 +40,20 @@ func New(dbType, connectionString string) (*SQLStore, error) {
err = store.Migrate()
if err != nil {
log.Println(`Table creation failed`)
return nil, err
}
return store, nil
}
// Shutdown close the connection with the store.
func (s *SQLStore) Shutdown() error {
return s.db.Close()
}
func (s *SQLStore) getQueryBuilder() sq.StatementBuilderType {
builder := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)
return builder.RunWith(s.db)
}

View File

@ -12,6 +12,7 @@ func SetupTests(t *testing.T) (*SQLStore, func()) {
if dbType == "" {
dbType = "sqlite3"
}
connectionString := os.Getenv("OT_STORE_TEST_CONN_STRING")
if connectionString == "" {
connectionString = ":memory:"
@ -24,5 +25,6 @@ func SetupTests(t *testing.T) (*SQLStore, func()) {
err = store.Shutdown()
require.Nil(t, err)
}
return store, tearDown
}

View File

@ -14,10 +14,12 @@ func (s *SQLStore) GetSystemSettings() (map[string]string, error) {
for rows.Next() {
var id string
var value string
err := rows.Scan(&id, &value)
if err != nil {
return nil, err
}
results[id] = value
}
@ -31,5 +33,6 @@ func (s *SQLStore) SetSystemSetting(id string, value string) error {
if err != nil {
return err
}
return nil
}

View File

@ -3,7 +3,7 @@ package store
import "github.com/mattermost/mattermost-octo-tasks/server/model"
// Store represents the abstraction of the data storage
// Store represents the abstraction of the data storage.
type Store interface {
GetBlocksWithParentAndType(parentID string, blockType string) ([]model.Block, error)
GetBlocksWithParent(parentID string) ([]model.Block, error)

View File

@ -40,6 +40,7 @@ func New(telemetryID string, log *log.Logger) *Service {
telemetryID: telemetryID,
trackers: map[string]Tracker{},
}
return service
}
@ -93,6 +94,7 @@ func (ts *Service) initRudder(endpoint string, rudderKey string) {
client, err := rudder.NewWithConfig(rudderKey, endpoint, config)
if err != nil {
ts.log.Fatal("Failed to create Rudder instance")
return
}
client.Enqueue(rudder.Identify{
@ -135,5 +137,6 @@ func (ts *Service) Shutdown() error {
if ts.rudderClient != nil {
return ts.rudderClient.Close()
}
return nil
}

View File

@ -11,21 +11,26 @@ import (
"github.com/gorilla/mux"
)
// RoutedService defines the interface that is needed for any service to
// register themself in the web server to provide new endpoints. (see
// AddRoutes).
type RoutedService interface {
RegisterRoutes(*mux.Router)
}
type WebServer struct {
// Server is the structure responsible for managing our http web server.
type Server struct {
router *mux.Router
rootPath string
port int
ssl bool
}
func NewWebServer(rootPath string, port int, ssl bool) *WebServer {
// NewServer creates a new instance of the webserver.
func NewServer(rootPath string, port int, ssl bool) *Server {
r := mux.NewRouter()
ws := &WebServer{
ws := &Server{
router: r,
rootPath: rootPath,
port: port,
@ -35,11 +40,12 @@ func NewWebServer(rootPath string, port int, ssl bool) *WebServer {
return ws
}
func (ws *WebServer) AddRoutes(rs RoutedService) {
// AddRoutes allows services to register themself in the webserver router and provide new endpoints.
func (ws *Server) AddRoutes(rs RoutedService) {
rs.RegisterRoutes(ws.router)
}
func (ws *WebServer) registerRoutes() {
func (ws *Server) registerRoutes() {
ws.router.PathPrefix("/static").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(filepath.Join(ws.rootPath, "static")))))
ws.router.PathPrefix("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
@ -47,12 +53,13 @@ func (ws *WebServer) registerRoutes() {
})
}
func (ws *WebServer) Start() error {
// Start runs the web server and start listening for charsetnnections.
func (ws *Server) Start() error {
ws.registerRoutes()
http.Handle("/", ws.router)
urlPort := fmt.Sprintf(`:%d`, ws.port)
var isSSL = ws.ssl && fileExists("./cert/cert.pem") && fileExists("./cert/key.pem")
isSSL := ws.ssl && fileExists("./cert/cert.pem") && fileExists("./cert/key.pem")
if isSSL {
log.Println("https server started on ", urlPort)
@ -73,7 +80,7 @@ func (ws *WebServer) Start() error {
return nil
}
// FileExists returns true if a file exists at the path
// fileExists returns true if a file exists at the path.
func fileExists(path string) bool {
_, err := os.Stat(path)
if os.IsNotExist(err) {

View File

@ -10,12 +10,12 @@ import (
"github.com/gorilla/websocket"
)
// RegisterRoutes registeres routes
// RegisterRoutes registers routes.
func (ws *Server) RegisterRoutes(r *mux.Router) {
r.HandleFunc("/ws/onchange", ws.handleWebSocketOnChange)
}
// AddListener adds a listener for a block's change
// AddListener adds a listener for a block's change.
func (ws *Server) AddListener(client *websocket.Conn, blockIDs []string) {
ws.mu.Lock()
for _, blockID := range blockIDs {
@ -28,23 +28,24 @@ func (ws *Server) AddListener(client *websocket.Conn, blockIDs []string) {
ws.mu.Unlock()
}
// RemoveListener removes a webSocket listener from all blocks
// RemoveListener removes a webSocket listener from all blocks.
func (ws *Server) RemoveListener(client *websocket.Conn) {
ws.mu.Lock()
for key, clients := range ws.listeners {
var listeners = []*websocket.Conn{}
listeners := []*websocket.Conn{}
for _, existingClient := range clients {
if client != existingClient {
listeners = append(listeners, existingClient)
}
}
ws.listeners[key] = listeners
}
ws.mu.Unlock()
}
// RemoveListenerFromBlocks removes a webSocket listener from a set of block
// RemoveListenerFromBlocks removes a webSocket listener from a set of block.
func (ws *Server) RemoveListenerFromBlocks(client *websocket.Conn, blockIDs []string) {
ws.mu.Lock()
@ -69,7 +70,7 @@ func (ws *Server) RemoveListenerFromBlocks(client *websocket.Conn, blockIDs []st
ws.mu.Unlock()
}
// GetListeners returns the listeners to a blockID's changes
// GetListeners returns the listeners to a blockID's changes.
func (ws *Server) GetListeners(blockID string) []*websocket.Conn {
ws.mu.Lock()
listeners := ws.listeners[blockID]
@ -78,14 +79,14 @@ func (ws *Server) GetListeners(blockID string) []*websocket.Conn {
return listeners
}
// Server is a WebSocket server
// Server is a WebSocket server.
type Server struct {
upgrader websocket.Upgrader
listeners map[string][]*websocket.Conn
mu sync.RWMutex
}
// NewServer creates a new Server
// NewServer creates a new Server.
func NewServer() *Server {
return &Server{
listeners: make(map[string][]*websocket.Conn),
@ -97,13 +98,13 @@ func NewServer() *Server {
}
}
// WebsocketMsg is sent on block changes
// WebsocketMsg is sent on block changes.
type WebsocketMsg struct {
Action string `json:"action"`
BlockID string `json:"blockId"`
}
// WebsocketCommand is an incoming command from the client
// WebsocketCommand is an incoming command from the client.
type WebsocketCommand struct {
Action string `json:"action"`
BlockIDs []string `json:"blockIds"`
@ -141,6 +142,7 @@ func (ws *Server) handleWebSocketOnChange(w http.ResponseWriter, r *http.Request
}
var command WebsocketCommand
err = json.Unmarshal(p, &command)
if err != nil {
// handle this error
@ -164,20 +166,21 @@ func (ws *Server) handleWebSocketOnChange(w http.ResponseWriter, r *http.Request
}
}
// BroadcastBlockChangeToWebsocketClients broadcasts change to clients
// BroadcastBlockChangeToWebsocketClients broadcasts change to clients.
func (ws *Server) BroadcastBlockChangeToWebsocketClients(blockIDs []string) {
for _, blockID := range blockIDs {
listeners := ws.GetListeners(blockID)
log.Printf("%d listener(s) for blockID: %s", len(listeners), blockID)
if listeners != nil {
var message = WebsocketMsg{
message := WebsocketMsg{
Action: "UPDATE_BLOCK",
BlockID: blockID,
}
for _, listener := range listeners {
log.Printf("Broadcast change, blockID: %s, remoteAddr: %s", blockID, listener.RemoteAddr())
err := listener.WriteJSON(message)
if err != nil {
log.Printf("broadcast error: %v", err)