Skip to content

Commit

Permalink
Query rewrite and bug fix (#478)
Browse files Browse the repository at this point in the history
* Rewrite Query as a real Doer, without doing.doify.

* Fix OOBIEnd to not reply to an OOBI request for an AID that doesn't have a threshold satisfying number of witness receipts.

* Removing dependency on codecov PyPi package that was unceremoniously removed from PyPi today.

* Attempt to reestablish codecov upload using github action.



---------

Signed-off-by: pfeairheller <pfeairheller@gmail.com>
  • Loading branch information
pfeairheller committed Apr 12, 2023
1 parent 0140cff commit dc2095d
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 111 deletions.
9 changes: 6 additions & 3 deletions .github/workflows/python-app-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,15 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest pytest-cov codecov hio
pip install pytest pytest-cov hio
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Run core KERI tests
run: |
pytest --cov=./ --cov-report=xml
codecov
- name: Upload
uses: codecov/codecov-action@v3
with:
token: 5eb1c60e-8b43-45f1-a003-357b240061cd

scripts:
runs-on: ubuntu-latest
Expand All @@ -72,7 +75,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest pytest-cov codecov hio pytest-shell
pip install pytest pytest-cov hio pytest-shell
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Run KERI kli tests
run: |
Expand Down
146 changes: 57 additions & 89 deletions src/keri/app/querying.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,117 +5,85 @@
"""

from hio.base import doing
from hio.help import decking

from keri.app import agenting


class QueryDoer(doing.DoDoer):

def __init__(self, hby, hab, kvy, pre, **kwa):
doers = []

self.hby = hby
self.hab = hab
self.kvy = kvy
self.logs = decking.Deck()

self.pre = pre
self.loaded = False

self.witq = agenting.WitnessInquisitor(hby=self.hby)
doers.extend([self.witq, doing.doify(self.keyStateCueDo), doing.doify(self.logsDo)])

self.toRemove = list(doers)
doers.extend([doing.doify(self.queryDo)])
doers = [KeyStateNoticer(hby=hby, hab=self.hab, pre=pre, cues=kvy.cues)]
super(QueryDoer, self).__init__(doers=doers, **kwa)

def queryDo(self, tymth, tock=0.0, **opts):
"""
Returns: doifiable Doist compatible generator method
Usage:
add result of doify on this method to doers list
"""
# enter context
self.wind(tymth)
self.tock = tock
_ = (yield self.tock)

class KeyStateNoticer(doing.DoDoer):

def __init__(self, hby, hab, pre, cues, **opts):
self.hby = hby
self.hab = hab
self.pre = pre
self.cues = cues
self.witq = agenting.WitnessInquisitor(hby=self.hby)
self.witq.query(src=self.hab.pre, pre=self.pre, r="ksn")

while not self.loaded:
yield 1.0
super(KeyStateNoticer, self).__init__(doers=[self.witq], **opts)

self.remove(self.toRemove)
def recur(self, tyme, deeds=None):
if self.pre in self.hby.kevers:
kever = self.hby.kevers[self.pre]
else:
return super(KeyStateNoticer, self).recur(tyme, deeds)

return
if self.cues:
cue = self.cues.popleft()
match cue['kin']:
case "keyStateSaved":
kcue = cue
ksn = kcue['serder']
match ksn.pre:
case self.pre:
if kever.sn < ksn.sn:
# Add new doer here instead of cueing to a while loop
print("New key events are available, loading now...")
self.extend([LogQuerier(hby=self.hby, hab=self.hab, ksn=ksn)])
self.remove([self.witq])

def keyStateCueDo(self, tymth, tock=0.0, **opts):
"""
Returns: doifiable Doist compatible generator method
Usage:
add result of doify on this method to doers list
"""
# enter context
self.wind(tymth)
self.tock = tock
_ = (yield self.tock)

while True:
if self.pre in self.hby.kevers:
kever = self.hab.kevers[self.pre]
else:
continue

kcue = None
for cue in self.kvy.cues:
match cue['kin']:
case "keyStateSaved":
kcue = cue
break

if kcue is not None:
self.kvy.cues.remove(kcue)

ksn = kcue['serder']
match ksn.pre:
case self.pre:
if kever.sn < ksn.sn:
print("New key events are available, loading now...")
self.logs.append(ksn)
else:
self.loaded = True

continue
case _:
continue

yield self.tock

def logsDo(self, tymth, tock=0.0, **opts):
else:
return True

case _:
self.cues.append(cue)

case _:
self.cues.append(cue)

return super(KeyStateNoticer, self).recur(tyme, deeds)


class LogQuerier(doing.DoDoer):

def __init__(self, hby, hab, ksn, **opts):
self.hby = hby
self.hab = hab
self.ksn = ksn
self.witq = agenting.WitnessInquisitor(hby=self.hby)
self.witq.query(src=self.hab.pre, pre=self.ksn.pre)
super(LogQuerier, self).__init__(doers=[self.witq], **opts)

def recur(self, tyme, deeds=None):
"""
Returns: doifiable Doist compatible generator method
Usage:
add result of doify on this method to doers list
"""
# enter context
self.wind(tymth)
self.tock = tock
_ = (yield self.tock)

while True:
while self.logs:
ksn = self.logs.popleft()
print(f"Querying for new events up to {ksn.sn}")
kever = self.hab.kevers[ksn.pre]

self.witq.query(src=self.hab.pre, pre=ksn.pre)

while kever.sn < ksn.sn:
yield self.tock

print("Key event log synced successfully")
self.loaded = True
return
kever = self.hab.kevers[self.ksn.pre]
if kever.sn >= self.ksn.sn:
self.remove([self.witq])
print("Key event log synced successfully")
return True

yield self.tock
return super(LogQuerier, self).recur(tyme, deeds)
4 changes: 4 additions & 0 deletions src/keri/end/ending.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,10 @@ def on_get(self, req, rep, aid=None, role=None, eid=None):
return

kever = self.hby.kevers[aid]
if not self.hby.db.fullyWitnessed(kever.serder):
rep.status = falcon.HTTP_NOT_FOUND
return

owits = oset(kever.wits)
if kever.prefixer.qb64 in self.hby.prefixes: # One of our identifiers
hab = self.hby.habs[kever.prefixer.qb64]
Expand Down
42 changes: 23 additions & 19 deletions tests/app/test_querying.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@
from hio.base import doing

from keri.app import habbing
from keri.app.querying import QueryDoer
from keri.app.querying import QueryDoer, KeyStateNoticer, LogQuerier
from keri.core import parsing


def test_querying():
with habbing.openHby() as hby, \
habbing.openHby() as hby1:
print()
inqHab = hby.makeHab(name="inquisitor")
subHab = hby1.makeHab(name="subject")
qdoer = QueryDoer(hby=hby, hab=inqHab, kvy=hby.kvy, pre=subHab.pre)
Expand All @@ -29,16 +28,20 @@ def test_querying():

# doist.do(doers=doers)
deeds = doist.enter(doers=[qdoer])
doist.recur(deeds=deeds)

assert len(qdoer.witq.msgs) == 1
msg = qdoer.witq.msgs.popleft()
assert len(qdoer.doers) == 1
ksnDoer = qdoer.doers[0]
assert isinstance(ksnDoer, KeyStateNoticer)
assert len(ksnDoer.witq.msgs) == 1
msg = ksnDoer.witq.msgs.popleft()
assert msg["src"] == inqHab.pre
assert msg["pre"] == subHab.pre
assert msg["r"] == "ksn"
assert msg["q"] == {'s': 0}
assert msg["wits"] is None

doist.recur(deeds=deeds)

# Cue up a saved key state equal to the one we have
hby.kvy.cues.clear()
ksn = subHab.kever.state()
Expand All @@ -48,7 +51,7 @@ def test_querying():
doist.recur(deeds=deeds)

# We already have up to date key state so loaded will be true
assert qdoer.loaded is True
assert qdoer.done is True
assert len(hby.kvy.cues) == 0

# create a new query doer
Expand All @@ -58,25 +61,26 @@ def test_querying():
doist = doing.Doist(limit=limit, tock=tock, real=True)

# rotate AID and submit as a new keyStateSave
subHab.rotate()
rot = subHab.rotate()
ksn = subHab.kever.state()
cue = dict(kin="keyStateSaved", serder=ksn)
hby.kvy.cues.append(cue)

deeds = doist.enter(doers=[qdoer])
doist.recur(deeds=deeds)

# We are behind in key state, so we aren't done and have queried for the logs
assert qdoer.loaded is False
assert len(qdoer.witq.msgs) == 2
msg = qdoer.witq.msgs[0]
assert msg["src"] == inqHab.pre
assert msg["pre"] == subHab.pre
assert msg["r"] == "logs"
assert msg["q"] == {'s': 0}
assert msg["wits"] is None
assert qdoer.done is False
assert len(qdoer.doers) == 1
ksnDoer = qdoer.doers[0]
assert isinstance(ksnDoer, KeyStateNoticer)
assert len(ksnDoer.witq.msgs) == 1

assert len(ksnDoer.doers) == 1
logDoer = ksnDoer.doers[0]
assert isinstance(logDoer, LogQuerier)
assert len(hby.kvy.cues) == 0

icp = subHab.makeOwnEvent(sn=1)
parsing.Parser().parseOne(ims=bytearray(icp), kvy=inqHab.kvy)
parsing.Parser().parseOne(ims=bytearray(rot), kvy=inqHab.kvy)
doist.recur(deeds=deeds)
assert qdoer.loaded is True

assert qdoer.done is True

0 comments on commit dc2095d

Please sign in to comment.