fix: block filters can be also recreated (#85)
* fix: block filters can be also recreated * refactor: rename filter to logFilter
This commit is contained in:
parent
d60cedbb98
commit
80b2ead97c
|
@ -140,7 +140,7 @@ type
|
||||||
# We need to keep around the filters that are used to create log filters on the RPC node
|
# We need to keep around the filters that are used to create log filters on the RPC node
|
||||||
# as there might be a time when they need to be recreated as RPC node might prune/forget
|
# as there might be a time when they need to be recreated as RPC node might prune/forget
|
||||||
# about them
|
# about them
|
||||||
filters: Table[JsonNode, EventFilter]
|
logFilters: Table[JsonNode, EventFilter]
|
||||||
|
|
||||||
# Used when filters are recreated to translate from the id that user
|
# Used when filters are recreated to translate from the id that user
|
||||||
# originally got returned to new filter id
|
# originally got returned to new filter id
|
||||||
|
@ -167,8 +167,15 @@ proc new*(_: type JsonRpcSubscriptions,
|
||||||
raise e
|
raise e
|
||||||
except CatchableError as e:
|
except CatchableError as e:
|
||||||
if "filter not found" in e.msg:
|
if "filter not found" in e.msg:
|
||||||
let filter = subscriptions.filters[originalId]
|
var newId: JsonNode
|
||||||
let newId = await subscriptions.client.eth_newFilter(filter)
|
# Log filters are stored in logFilters, block filters are not persisted
|
||||||
|
# there is they do not need any specific data for their recreation.
|
||||||
|
# We use this to determine if the filter was log or block filter here.
|
||||||
|
if subscriptions.logFilters.hasKey(originalId):
|
||||||
|
let filter = subscriptions.logFilters[originalId]
|
||||||
|
newId = await subscriptions.client.eth_newFilter(filter)
|
||||||
|
else:
|
||||||
|
newId = await subscriptions.client.eth_newBlockFilter()
|
||||||
subscriptions.subscriptionMapping[originalId] = newId
|
subscriptions.subscriptionMapping[originalId] = newId
|
||||||
return await getChanges(originalId)
|
return await getChanges(originalId)
|
||||||
else:
|
else:
|
||||||
|
@ -225,14 +232,14 @@ method subscribeLogs(subscriptions: PollingSubscriptions,
|
||||||
|
|
||||||
let id = await subscriptions.client.eth_newFilter(filter)
|
let id = await subscriptions.client.eth_newFilter(filter)
|
||||||
subscriptions.callbacks[id] = callback
|
subscriptions.callbacks[id] = callback
|
||||||
subscriptions.filters[id] = filter
|
subscriptions.logFilters[id] = filter
|
||||||
subscriptions.subscriptionMapping[id] = id
|
subscriptions.subscriptionMapping[id] = id
|
||||||
return id
|
return id
|
||||||
|
|
||||||
method unsubscribe*(subscriptions: PollingSubscriptions,
|
method unsubscribe*(subscriptions: PollingSubscriptions,
|
||||||
id: JsonNode)
|
id: JsonNode)
|
||||||
{.async.} =
|
{.async.} =
|
||||||
subscriptions.filters.del(id)
|
subscriptions.logFilters.del(id)
|
||||||
subscriptions.callbacks.del(id)
|
subscriptions.callbacks.del(id)
|
||||||
let sub = subscriptions.subscriptionMapping[id]
|
let sub = subscriptions.subscriptionMapping[id]
|
||||||
subscriptions.subscriptionMapping.del(id)
|
subscriptions.subscriptionMapping.del(id)
|
||||||
|
|
|
@ -25,6 +25,11 @@ proc start*(server: MockRpcHttpServer) =
|
||||||
server.filters.add filterId
|
server.filters.add filterId
|
||||||
return filterId
|
return filterId
|
||||||
|
|
||||||
|
server.srv.router.rpc("eth_newBlockFilter") do() -> string:
|
||||||
|
let filterId = "0x" & (array[16, byte].example).toHex
|
||||||
|
server.filters.add filterId
|
||||||
|
return filterId
|
||||||
|
|
||||||
server.srv.router.rpc("eth_getFilterChanges") do(id: string) -> seq[string]:
|
server.srv.router.rpc("eth_getFilterChanges") do(id: string) -> seq[string]:
|
||||||
if id notin server.filters:
|
if id notin server.filters:
|
||||||
raise (ref ApplicationError)(code: -32000, msg: "filter not found")
|
raise (ref ApplicationError)(code: -32000, msg: "filter not found")
|
||||||
|
|
|
@ -124,25 +124,25 @@ suite "HTTP polling subscriptions - filter not found":
|
||||||
await client.close()
|
await client.close()
|
||||||
await mockServer.stop()
|
await mockServer.stop()
|
||||||
|
|
||||||
test "filter not found error recreates filter":
|
test "filter not found error recreates log filter":
|
||||||
let filter = EventFilter(address: Address.example, topics: @[array[32, byte].example])
|
let filter = EventFilter(address: Address.example, topics: @[array[32, byte].example])
|
||||||
let emptyHandler = proc(log: Log) = discard
|
let emptyHandler = proc(log: Log) = discard
|
||||||
|
|
||||||
check subscriptions.filters.len == 0
|
check subscriptions.logFilters.len == 0
|
||||||
check subscriptions.subscriptionMapping.len == 0
|
check subscriptions.subscriptionMapping.len == 0
|
||||||
|
|
||||||
let id = await subscriptions.subscribeLogs(filter, emptyHandler)
|
let id = await subscriptions.subscribeLogs(filter, emptyHandler)
|
||||||
|
|
||||||
check subscriptions.filters[id] == filter
|
check subscriptions.logFilters[id] == filter
|
||||||
check subscriptions.subscriptionMapping[id] == id
|
check subscriptions.subscriptionMapping[id] == id
|
||||||
check subscriptions.filters.len == 1
|
check subscriptions.logFilters.len == 1
|
||||||
check subscriptions.subscriptionMapping.len == 1
|
check subscriptions.subscriptionMapping.len == 1
|
||||||
|
|
||||||
mockServer.invalidateFilter(id)
|
mockServer.invalidateFilter(id)
|
||||||
|
|
||||||
check eventually subscriptions.subscriptionMapping[id] != id
|
check eventually subscriptions.subscriptionMapping[id] != id
|
||||||
|
|
||||||
test "recreated filter can be still unsubscribed using the original id":
|
test "recreated log filter can be still unsubscribed using the original id":
|
||||||
let filter = EventFilter(address: Address.example, topics: @[array[32, byte].example])
|
let filter = EventFilter(address: Address.example, topics: @[array[32, byte].example])
|
||||||
let emptyHandler = proc(log: Log) = discard
|
let emptyHandler = proc(log: Log) = discard
|
||||||
let id = await subscriptions.subscribeLogs(filter, emptyHandler)
|
let id = await subscriptions.subscribeLogs(filter, emptyHandler)
|
||||||
|
@ -151,5 +151,26 @@ suite "HTTP polling subscriptions - filter not found":
|
||||||
|
|
||||||
await subscriptions.unsubscribe(id)
|
await subscriptions.unsubscribe(id)
|
||||||
|
|
||||||
check not subscriptions.filters.hasKey id
|
check not subscriptions.logFilters.hasKey id
|
||||||
|
check not subscriptions.subscriptionMapping.hasKey id
|
||||||
|
|
||||||
|
test "filter not found error recreates block filter":
|
||||||
|
let emptyHandler = proc(blck: Block) = discard
|
||||||
|
|
||||||
|
check subscriptions.subscriptionMapping.len == 0
|
||||||
|
let id = await subscriptions.subscribeBlocks(emptyHandler)
|
||||||
|
check subscriptions.subscriptionMapping[id] == id
|
||||||
|
|
||||||
|
mockServer.invalidateFilter(id)
|
||||||
|
|
||||||
|
check eventually subscriptions.subscriptionMapping[id] != id
|
||||||
|
|
||||||
|
test "recreated block filter can be still unsubscribed using the original id":
|
||||||
|
let emptyHandler = proc(blck: Block) = discard
|
||||||
|
let id = await subscriptions.subscribeBlocks(emptyHandler)
|
||||||
|
mockServer.invalidateFilter(id)
|
||||||
|
check eventually subscriptions.subscriptionMapping[id] != id
|
||||||
|
|
||||||
|
await subscriptions.unsubscribe(id)
|
||||||
|
|
||||||
check not subscriptions.subscriptionMapping.hasKey id
|
check not subscriptions.subscriptionMapping.hasKey id
|
||||||
|
|
Loading…
Reference in New Issue