Skip to content

Commit

Permalink
Merge pull request #224 from GNS-Science/feature/223_AT_supports_all_…
Browse files Browse the repository at this point in the history
…IS_types

inversionSolution resolver for AutomationTask
  • Loading branch information
chrisbc authored Jun 27, 2024
2 parents b91f124 + 6984842 commit 805f26c
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 19 deletions.
24 changes: 19 additions & 5 deletions graphql_api/schema/custom/automation_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ class Meta:
model_type = ModelType()
task_type = TaskSubType()
inversion_solution = graphene.Field(
'graphql_api.schema.custom.inversion_solution.InversionSolution',
description="the primary result of this task (only for task_type == INVERSION.",
'graphql_api.schema.custom.inversion_solution_union.InversionSolutionUnion',
description="the result of this task. NB only available for task_types:"
"INVERSION, SCALE_SOLUTION, AGGREGATE_SOLUTION, TIME_DEPENDENT_SOLUTION.",
)

@staticmethod
Expand All @@ -56,16 +57,27 @@ def from_json(jsondata):

@staticmethod
def resolve_inversion_solution(root, info, **args):

log.info(f"resolve_inversion_solution {root.task_type}")
resolvable_types = [
TaskSubType.INVERSION.value,
TaskSubType.SCALE_SOLUTION.value,
TaskSubType.AGGREGATE_SOLUTION.value,
TaskSubType.TIME_DEPENDENT_SOLUTION.value,
]

if not len(root.files):
return
if not root.task_type == TaskSubType.INVERSION.value:
if root.task_type not in resolvable_types:
log.info(f"Cannot resove inversion_soluton for {root.task_type}")
return

t0 = dt.utcnow()
res = None

# TODO this is an ugly hack....
# - It gets the inversion solution by traversing the file_relations until it finds an InversionSolution.
# - It gets the inversion solution by traversing the file_relations until it finds
# an InversionSolution subtype.
# - Instead this attribute needs to be a first-class one-to-one relationship
for file_id in root.files:
if isinstance(file_id, dict): # new form, files is list of objects
Expand All @@ -79,9 +91,11 @@ def resolve_inversion_solution(root, info, **args):
if not file_relation.role == FileRole.WRITE.value:
continue
file = get_data_manager().file.get_one(file_relation.file_id)
if file.__class__.__name__ == 'InversionSolution':
if 'InversionSolution' in file.__class__.__name__:
res = file
log.info(f"resolved inversion_solution file {file}")
break

db_metrics.put_duration(__name__, 'AutomationTask.resolve_inversion_solution', dt.utcnow() - t0)
return res

Expand Down
17 changes: 17 additions & 0 deletions graphql_api/schema/custom/inversion_solution_union.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# !inversion_solution_union.py
import graphene

from .aggregate_inversion_solution import AggregateInversionSolution
from .inversion_solution import InversionSolution
from .scaled_inversion_solution import ScaledInversionSolution
from .time_dependent_inversion_solution import TimeDependentInversionSolution


class InversionSolutionUnion(graphene.Union):
class Meta:
types = (
InversionSolution,
ScaledInversionSolution,
AggregateInversionSolution,
TimeDependentInversionSolution,
)
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ def test_task_product_query(self, mocked_api_DB):
id
created
inversion_solution {
id
file_name
... on Node { id }
... on FileInterface { file_name }
}
files {
total_count
Expand Down Expand Up @@ -183,8 +183,8 @@ def test_example_failing_product_query(self, mocked_api_DB):
id
created
inversion_solution {
id
file_name
... on Node { id }
... on FileInterface { file_name }
}
files {
total_count
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ def test_task_product_query(self, mocked_api):
id
created
inversion_solution {
id
file_name
... on Node { id }
... on FileInterface { file_name }
}
files {
total_count
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
"""
Test API function for GeneralTask
using moto mocking re issue #223
"""

import datetime as dt
import unittest

import boto3
from dateutil.tz import tzutc
from graphene.test import Client
from graphql_relay import from_global_id
from moto import mock_dynamodb, mock_s3
from pynamodb.connection.base import Connection # for mocking

from graphql_api.config import REGION, S3_BUCKET_NAME
from graphql_api.data import data_manager
from graphql_api.dynamodb.models import ToshiFileObject, ToshiIdentity, ToshiThingObject
from graphql_api.schema import root_schema
from graphql_api.schema.search_manager import SearchManager

from .hazard.setup_helpers import SetupHelpersMixin


@mock_dynamodb
@mock_s3
class TestScaledInversionSolution(unittest.TestCase, SetupHelpersMixin):
def setUp(self):
self.client = Client(root_schema)

# S3
self._s3 = boto3.resource('s3', region_name=REGION)
self._s3.create_bucket(Bucket=S3_BUCKET_NAME)

# Dynamo
self._connection = Connection(region=REGION)

ToshiThingObject.create_table()
ToshiFileObject.create_table()
ToshiIdentity.create_table()

self._data_manager = data_manager.DataManager(search_manager=SearchManager('test', 'test', {'fake': 'auth'}))

upstream_sid = self.create_source_solution()
self.new_gt = self.create_general_task()
self.at_id = self.create_automation_task("SCALE_SOLUTION")
self.create_gt_relation(self.new_gt, self.at_id)

result = self.create_scaled_solution(upstream_sid, self.at_id)

ss = result['data']['create_scaled_inversion_solution']['solution']
self.scaled_solution_id = ss['id']

# def create_task_file(self, task_id, file_id, role):
qry2 = '''
mutation create_file_relation(
$thing_id:ID!
$file_id:ID!
$role:FileRole!) {
create_file_relation(
file_id:$file_id
thing_id:$thing_id
role:$role
)
{
ok
}
}'''
variables = dict(thing_id=self.at_id, file_id=self.at_id, role='WRITE')
executed = self.client.execute(qry2, variable_values=variables)
print('created file relation', executed)

def test_general_task_query(self):
print("self.new_gt", self.new_gt)

qry = '''
query GeneralTaskChildrenTabQuery($id: ID!) {
node(id: $id) {
... on GeneralTask {
id
model_type
children {
edges {
node {
child {
__typename
... on Node {
id
}
...on AutomationTask {
task_type
inversion_solution {
__typename
... on Node {
id
}
}
}
... on AutomationTaskInterface {
state
result
created
duration
arguments {
k
v
}
}
}
}
}
}
}
}
}
'''

print(qry)
executed = self.client.execute(qry, variable_values=dict(id=self.new_gt))
print(executed)

node = executed['data']['node']
assert node['id'] == self.new_gt
assert node['children']['edges'][0]['node']['child']['__typename'] == "AutomationTask"
assert node['children']['edges'][0]['node']['child']['inversion_solution']['__typename']
assert node['children']['edges'][0]['node']['child']['inversion_solution']['id'] == self.scaled_solution_id
assert (
node['children']['edges'][0]['node']['child']['inversion_solution']['__typename']
== "ScaledInversionSolution"
)
20 changes: 12 additions & 8 deletions graphql_api/tests/test_inversion_solution_bug_93.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,19 @@ def test_query_with_files(self, mocked_read_object, mocked_get_one):
task_type
id
inversion_solution {
id
file_name
meta {
k
v
... on Node { id }
... on FileInterface {
file_name
meta {
k
v
}
}
tables {
table_id
table_type
... on InversionSolutionInterface {
tables {
table_id
table_type
}
}
}
}
Expand Down

0 comments on commit 805f26c

Please sign in to comment.