Skip to content

Commit

Permalink
Feature to get a list of long running operations (#158)
Browse files Browse the repository at this point in the history
* add/operations endpoint

* add type filtering parameter to getOperations

* getOperations catches error from Monitor.status

* add unit test, cleanup

* cleanup

* api documentation

* spec update - adding new endpoint

---------

Co-authored-by: Petteri Stenius <[email protected]>
  • Loading branch information
psteniusubi and psteniusubi authored Jan 11, 2024
1 parent f67227a commit eb163c5
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 204 deletions.
6 changes: 4 additions & 2 deletions src/keria/app/agenting.py
Original file line number Diff line number Diff line change
Expand Up @@ -757,8 +757,10 @@ def recur(self, tyme):


def loadEnds(app):
opEnd = longrunning.OperationResourceEnd()
app.add_route("/operations/{name}", opEnd)
opColEnd = longrunning.OperationCollectionEnd()
app.add_route("/operations", opColEnd)
opResEnd = longrunning.OperationResourceEnd()
app.add_route("/operations/{name}", opResEnd)

oobiColEnd = OOBICollectionEnd()
app.add_route("/oobis", oobiColEnd)
Expand Down
55 changes: 55 additions & 0 deletions src/keria/core/longrunning.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from dataclasses import dataclass, asdict

import falcon
import json
from dataclasses_json import dataclass_json
from keri import kering
from keri.app.oobiing import Result
Expand Down Expand Up @@ -138,6 +139,26 @@ def get(self, name):

return operation

def getOperations(self, type=None):
""" Return list of long running opterations, optionally filtered by type """
ops = self.opr.ops.getItemIter()
if type != None:
ops = filter(lambda i: i[1].type == type, ops)

def get_status(op):
try:
return self.status(op)
except Exception as err:
# self.status may throw an exception.
# Handling error by returning an operation with error status
return Operation(
name=f"{op.type}.{op.oid}",
metadata=op.metadata,
done=True,
error=Status(code=500, message=f"{err}"))

return [get_status(op) for (_, op) in ops]

def rem(self, name):
""" Remove tracking of the long running operation represented by name """
return self.opr.ops.rem(keys=(name,))
Expand Down Expand Up @@ -365,6 +386,40 @@ def status(self, op):
return operation


class OperationCollectionEnd:
@staticmethod
def on_get(req, rep):
""" Get list of long running operations
Parameters:
req (Request): Falcon HTTP Request object
rep (Response): Falcon HTTP Response object
---
summary: Get list of long running operations
parameters:
- in: query
name: type
schema:
type: string
required: false
description: filter list of long running operations by type
responses:
200:
content:
application/json:
schema:
type: array
"""
agent = req.context.agent
type = req.params.get("type")
ops = agent.monitor.getOperations(type=type)
rep.data = json.dumps(ops, default=lambda o: o.to_dict()).encode("utf-8")
rep.content_type = "application/json"
rep.status = falcon.HTTP_200


class OperationResourceEnd:
""" Single Resource REST endpoint for long running operations
Expand Down
Loading

0 comments on commit eb163c5

Please sign in to comment.