-
Notifications
You must be signed in to change notification settings - Fork 110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dot/rpc implement state_subscribeStorage RPC WebSocket method #983
Changes from 24 commits
8dcd114
1839679
e17115c
cb68030
a4a06d1
4e92819
4dd45e3
452a7a1
d822106
631f942
2696608
b7ff1ce
5bdbe0e
9389b5b
884c523
0d62122
ce4837c
8d533ca
46db2f6
0d19256
005f4e6
cb3c502
f9d65f0
85b6602
bd6e9d9
b0be8f1
cf9cc48
31f6b5a
bde2c68
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,23 +20,21 @@ import ( | |
"fmt" | ||
"net/http" | ||
"os" | ||
"sync" | ||
|
||
"github.com/ChainSafe/gossamer/dot/rpc/modules" | ||
"github.com/ChainSafe/gossamer/dot/types" | ||
log "github.com/ChainSafe/log15" | ||
"github.com/gorilla/mux" | ||
"github.com/gorilla/rpc/v2" | ||
"github.com/gorilla/websocket" | ||
|
||
log "github.com/ChainSafe/log15" | ||
) | ||
|
||
// HTTPServer gateway for RPC server | ||
type HTTPServer struct { | ||
logger log.Logger | ||
rpcServer *rpc.Server // Actual RPC call handler | ||
serverConfig *HTTPServerConfig | ||
blockChan chan *types.Block | ||
chanID byte // channel ID | ||
wsConns []*WSConn | ||
} | ||
|
||
// HTTPServerConfig configures the HTTPServer | ||
|
@@ -56,13 +54,18 @@ type HTTPServerConfig struct { | |
WSEnabled bool | ||
WSPort uint32 | ||
Modules []string | ||
WSSubscriptions map[uint32]*WebSocketSubscription | ||
} | ||
|
||
// WebSocketSubscription holds subscription details | ||
type WebSocketSubscription struct { | ||
WSConnection *websocket.Conn | ||
SubscriptionType int | ||
// WSConn struct to hold WebSocket Connection references | ||
type WSConn struct { | ||
wsconn *websocket.Conn | ||
mu sync.Mutex | ||
serverConfig *HTTPServerConfig | ||
logger log.Logger | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. might be nice to make the logger global to the rpc package There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good idea. |
||
blockSubChannels map[int]byte | ||
storageSubChannels map[int]byte | ||
qtyListeners int | ||
subscriptions map[int]Listener | ||
} | ||
|
||
// NewHTTPServer creates a new http server and registers an associated rpc server | ||
|
@@ -77,10 +80,6 @@ func NewHTTPServer(cfg *HTTPServerConfig) *HTTPServer { | |
serverConfig: cfg, | ||
} | ||
|
||
if cfg.WSSubscriptions == nil { | ||
cfg.WSSubscriptions = make(map[uint32]*WebSocketSubscription) | ||
} | ||
|
||
server.RegisterModules(cfg.Modules) | ||
return server | ||
} | ||
|
@@ -151,25 +150,30 @@ func (h *HTTPServer) Start() error { | |
} | ||
}() | ||
|
||
// init and start block received listener routine | ||
if h.serverConfig.BlockAPI != nil { | ||
var err error | ||
h.blockChan = make(chan *types.Block) | ||
h.chanID, err = h.serverConfig.BlockAPI.RegisterImportedChannel(h.blockChan) | ||
if err != nil { | ||
return err | ||
} | ||
go h.blockReceivedListener() | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Stop stops the server | ||
func (h *HTTPServer) Stop() error { | ||
if h.serverConfig.WSEnabled { | ||
h.serverConfig.BlockAPI.UnregisterImportedChannel(h.chanID) | ||
close(h.blockChan) | ||
// close all channels and websocket connections | ||
for _, conn := range h.wsConns { | ||
for _, sub := range conn.subscriptions { | ||
switch v := sub.(type) { | ||
case *StorageChangeListener: | ||
h.serverConfig.StorageAPI.UnregisterStorageChangeChannel(v.chanID) | ||
close(v.channel) | ||
case *BlockListener: | ||
h.serverConfig.BlockAPI.UnregisterImportedChannel(v.chanID) | ||
close(v.channel) | ||
} | ||
} | ||
|
||
err := conn.wsconn.Close() | ||
if err != nil { | ||
h.logger.Error("error closing websocket connection", "error", err) | ||
} | ||
} | ||
} | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -285,9 +285,11 @@ func (sm *StateModule) SubscribeRuntimeVersion(r *http.Request, req *StateStorag | |
return sm.GetRuntimeVersion(r, nil, res) | ||
} | ||
|
||
// SubscribeStorage isn't implemented properly yet. | ||
func (sm *StateModule) SubscribeStorage(r *http.Request, req *StateStorageQueryRangeRequest, res *StorageChangeSetResponse) { | ||
// TODO implement change storage trie so that block hash parameter works (See issue #834) | ||
// SubscribeStorage Storage subscription. If storage keys are specified, it creates a message for each block which | ||
// changes the specified storage keys. If none are specified, then it creates a message for every block. | ||
// This endpoint communicates over the Websocket protocol, but this func should remain here so it's added to rpc_methods list | ||
func (sm *StateModule) SubscribeStorage(r *http.Request, req *StateStorageQueryRangeRequest, res *StorageChangeSetResponse) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm also wondering, is there an unsubscribe method corresponding to the subscribe methods? if so, it would be nice to return the subscription ID |
||
return nil | ||
} | ||
|
||
func convertAPIs(in []*runtime.API_Item) []interface{} { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this need the whole server config? or just the state interfaces?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No just BlockAPI and StorageAPI, I've updated.