deltafi 2.0rc1719271450675__py3-none-any.whl → 2.0rc1720728217472__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of deltafi might be problematic. Click here for more details.

deltafi/action.py CHANGED
@@ -20,17 +20,20 @@ from abc import ABC, abstractmethod
20
20
  from typing import Any, List
21
21
 
22
22
  from deltafi.actiontype import ActionType
23
- from deltafi.domain import Context, DeltaFileMessage
24
23
  from deltafi.genericmodel import GenericModel
25
- from deltafi.input import EgressInput, TransformInput
24
+ from deltafi.domain import Context, DeltaFileMessage
25
+ from deltafi.input import DomainInput, EgressInput, EnrichInput, FormatInput, LoadInput, TransformInput, ValidateInput
26
26
  from deltafi.result import *
27
27
  from pydantic import BaseModel
28
28
 
29
29
 
30
30
  class Action(ABC):
31
- def __init__(self, action_type: ActionType, description: str, valid_result_types: tuple):
31
+ def __init__(self, action_type: ActionType, description: str, requires_domains: List[str],
32
+ requires_enrichments: List[str], valid_result_types: tuple):
32
33
  self.action_type = action_type
33
34
  self.description = description
35
+ self.requires_domains = requires_domains
36
+ self.requires_enrichments = requires_enrichments
34
37
  self.valid_result_types = valid_result_types
35
38
  self.action_execution = None
36
39
 
@@ -48,23 +51,20 @@ class Action(ABC):
48
51
  def execute_action(self, event):
49
52
  if event.delta_file_messages is None or not len(event.delta_file_messages):
50
53
  raise RuntimeError(f"Received event with no delta file messages for did {event.context.did}")
54
+
51
55
  if event.context.collect is not None:
52
- result = self.execute(
53
- event.context,
54
- self.collect([self.build_input(event.context, delta_file_message)
55
- for delta_file_message in event.delta_file_messages]),
56
- self.param_class().model_validate(event.params))
56
+ result = self.execute(event.context, self.collect([self.build_input(event.context, delta_file_message)
57
+ for delta_file_message in event.delta_file_messages]),
58
+ self.param_class().model_validate(event.params))
57
59
  else:
58
- result = self.execute(
59
- event.context,
60
- self.build_input(event.context, event.delta_file_messages[0]),
61
- self.param_class().model_validate(event.params))
60
+ result = self.execute(event.context, self.build_input(event.context, event.delta_file_messages[0]),
61
+ self.param_class().model_validate(event.params))
62
62
 
63
63
  self.validate_type(result)
64
64
  return result
65
65
 
66
66
  @staticmethod
67
- def param_class():
67
+ def param_class( ):
68
68
  """Factory method to create and return an empty GenericModel instance.
69
69
 
70
70
  Returns
@@ -81,9 +81,25 @@ class Action(ABC):
81
81
  f"but a {result.__class__.__name__} was returned")
82
82
 
83
83
 
84
+ class DomainAction(Action, ABC):
85
+ def __init__(self, description: str, requires_domains: List[str]):
86
+ super().__init__(ActionType.DOMAIN, description, requires_domains, [], (DomainResult, ErrorResult))
87
+
88
+ def build_input(self, context: Context, delta_file_message: DeltaFileMessage):
89
+ return DomainInput(content=delta_file_message.content_list, metadata=delta_file_message.metadata,
90
+ domains={domain.name: domain for domain in delta_file_message.domains})
91
+
92
+ @abstractmethod
93
+ def domain(self, context: Context, params: BaseModel, domain_input: DomainInput):
94
+ pass
95
+
96
+ def execute(self, context: Context, domain_input: DomainInput, params: BaseModel):
97
+ return self.domain(context, params, domain_input)
98
+
99
+
84
100
  class EgressAction(Action, ABC):
85
101
  def __init__(self, description: str):
86
- super().__init__(ActionType.EGRESS, description, (EgressResult, ErrorResult, FilterResult))
102
+ super().__init__(ActionType.EGRESS, description, [], [], (EgressResult, ErrorResult, FilterResult))
87
103
 
88
104
  def build_input(self, context: Context, delta_file_message: DeltaFileMessage):
89
105
  return EgressInput(content=delta_file_message.content_list[0], metadata=delta_file_message.metadata)
@@ -96,9 +112,81 @@ class EgressAction(Action, ABC):
96
112
  return self.egress(context, params, egress_input)
97
113
 
98
114
 
115
+ class EnrichAction(Action, ABC):
116
+ def __init__(self, description: str, requires_domains: List[str], requires_enrichments: List[str]):
117
+ super().__init__(ActionType.ENRICH, description, requires_domains, requires_enrichments,
118
+ (EnrichResult, ErrorResult))
119
+
120
+ def build_input(self, context: Context, delta_file_message: DeltaFileMessage):
121
+ return EnrichInput(content=delta_file_message.content_list, metadata=delta_file_message.metadata,
122
+ domains={domain.name: domain for domain in delta_file_message.domains},
123
+ enrichments={domain.name: domain for domain in delta_file_message.enrichments})
124
+
125
+ @abstractmethod
126
+ def enrich(self, context: Context, params: BaseModel, enrich_input: EnrichInput):
127
+ pass
128
+
129
+ def execute(self, context: Context, enrich_input: EnrichInput, params: BaseModel):
130
+ return self.enrich(context, params, enrich_input)
131
+
132
+
133
+ class FormatAction(Action, ABC):
134
+ def __init__(self, description: str, requires_domains: List[str], requires_enrichments: List[str]):
135
+ super().__init__(ActionType.FORMAT, description, requires_domains, requires_enrichments,
136
+ (FormatResult, FormatManyResult, ErrorResult, FilterResult))
137
+
138
+ def build_input(self, context: Context, delta_file_message: DeltaFileMessage):
139
+ return FormatInput(content=delta_file_message.content_list, metadata=delta_file_message.metadata,
140
+ domains={domain.name: domain for domain in delta_file_message.domains},
141
+ enrichments={domain.name: domain for domain in delta_file_message.enrichments})
142
+
143
+ def collect(self, format_inputs: List[FormatInput]):
144
+ all_content = []
145
+ all_metadata = {}
146
+ all_domains = {}
147
+ all_enrichments = {}
148
+ for format_input in format_inputs:
149
+ all_content += format_input.content
150
+ all_metadata.update(format_input.metadata)
151
+ all_domains.update(format_input.domains)
152
+ all_enrichments.update(format_input.enrichments)
153
+ return FormatInput(content=all_content, metadata=all_metadata, domains=all_domains, enrichments=all_enrichments)
154
+
155
+ @abstractmethod
156
+ def format(self, context: Context, params: BaseModel, format_input: FormatInput):
157
+ pass
158
+
159
+ def execute(self, context: Context, format_input: FormatInput, params: BaseModel):
160
+ return self.format(context, params, format_input)
161
+
162
+
163
+ class LoadAction(Action, ABC):
164
+ def __init__(self, description: str):
165
+ super().__init__(ActionType.LOAD, description, [], [],
166
+ (LoadResult, LoadManyResult, ErrorResult, FilterResult, ReinjectResult))
167
+
168
+ def build_input(self, context: Context, delta_file_message: DeltaFileMessage):
169
+ return LoadInput(content=delta_file_message.content_list, metadata=delta_file_message.metadata)
170
+
171
+ def collect(self, load_inputs: List[LoadInput]):
172
+ all_content = []
173
+ all_metadata = {}
174
+ for load_input in load_inputs:
175
+ all_content += load_input.content
176
+ all_metadata.update(load_input.metadata)
177
+ return LoadInput(content=all_content, metadata=all_metadata)
178
+
179
+ @abstractmethod
180
+ def load(self, context: Context, params: BaseModel, load_input: LoadInput):
181
+ pass
182
+
183
+ def execute(self, context: Context, load_input: LoadInput, params: BaseModel):
184
+ return self.load(context, params, load_input)
185
+
186
+
99
187
  class TimedIngressAction(Action, ABC):
100
188
  def __init__(self, description: str):
101
- super().__init__(ActionType.TIMED_INGRESS, description, (IngressResult, ErrorResult))
189
+ super().__init__(ActionType.TIMED_INGRESS, description, [], [], (IngressResult, ErrorResult))
102
190
 
103
191
  def build_input(self, context: Context, delta_file_message: DeltaFileMessage):
104
192
  return None
@@ -113,8 +201,7 @@ class TimedIngressAction(Action, ABC):
113
201
 
114
202
  class TransformAction(Action, ABC):
115
203
  def __init__(self, description: str):
116
- super().__init__(ActionType.TRANSFORM, description,
117
- (TransformResult, TransformResults, ErrorResult, FilterResult))
204
+ super().__init__(ActionType.TRANSFORM, description, [], [], (TransformResult, ErrorResult, FilterResult, ReinjectResult))
118
205
 
119
206
  def build_input(self, context: Context, delta_file_message: DeltaFileMessage):
120
207
  return TransformInput(content=delta_file_message.content_list, metadata=delta_file_message.metadata)
@@ -133,3 +220,18 @@ class TransformAction(Action, ABC):
133
220
 
134
221
  def execute(self, context: Context, transform_input: TransformInput, params: BaseModel):
135
222
  return self.transform(context, params, transform_input)
223
+
224
+
225
+ class ValidateAction(Action, ABC):
226
+ def __init__(self, description: str):
227
+ super().__init__(ActionType.VALIDATE, description, [], [], (ValidateResult, ErrorResult, FilterResult))
228
+
229
+ def build_input(self, context: Context, delta_file_message: DeltaFileMessage):
230
+ return ValidateInput(content=delta_file_message.content_list[0], metadata=delta_file_message.metadata)
231
+
232
+ @abstractmethod
233
+ def validate(self, context: Context, params: BaseModel, validate_input: ValidateInput):
234
+ pass
235
+
236
+ def execute(self, context: Context, validate_input: ValidateInput, params: BaseModel):
237
+ return self.validate(context, params, validate_input)
deltafi/actiontype.py CHANGED
@@ -20,9 +20,13 @@ from enum import Enum
20
20
 
21
21
 
22
22
  class ActionType(Enum):
23
- INGRESS = "INGRESS"
24
23
  TIMED_INGRESS = "TIMED_INGRESS"
25
24
  TRANSFORM = "TRANSFORM"
25
+ LOAD = "LOAD"
26
+ DOMAIN = "DOMAIN"
27
+ ENRICH = "ENRICH"
28
+ FORMAT = "FORMAT"
29
+ VALIDATE = "VALIDATE"
26
30
  EGRESS = "EGRESS"
27
- PUBLISH = "PUBLISH"
31
+ DELETE = "DELETE"
28
32
  UNKNOWN = "UNKNOWN"
deltafi/domain.py CHANGED
@@ -40,15 +40,13 @@ class ActionExecution(NamedTuple):
40
40
 
41
41
  class Context(NamedTuple):
42
42
  did: str
43
- delta_file_name: str
44
- data_source: str
45
- flow_name: str
46
- flow_id: str
43
+ action_flow: str
47
44
  action_name: str
48
- action_id: str
49
- action_version: str
45
+ source_filename: str
46
+ ingress_flow: str
47
+ egress_flow: str
48
+ system: str
50
49
  hostname: str
51
- system_name: str
52
50
  content_service: ContentService
53
51
  collect: dict = None
54
52
  collected_dids: List[str] = None
@@ -56,44 +54,21 @@ class Context(NamedTuple):
56
54
  logger: Logger = None
57
55
 
58
56
  @classmethod
59
- def create(cls, context: dict, content_service: ContentService, logger: Logger):
57
+ def create(cls, context: dict, hostname: str, content_service: ContentService, logger: Logger):
60
58
  did = context['did']
61
- if 'deltaFileName' in context:
62
- delta_file_name = context['deltaFileName']
59
+ action_name_parts = context['name'].split(".")
60
+ action_flow = action_name_parts[0]
61
+ action_name = action_name_parts[1]
62
+ if 'sourceFilename' in context:
63
+ source_filename = context['sourceFilename']
63
64
  else:
64
- delta_file_name = None
65
- if 'dataSource' in context:
66
- data_source = context['dataSource']
65
+ source_filename = None
66
+ ingress_flow = context['ingressFlow']
67
+ if 'egressFlow' in context:
68
+ egress_flow = context['egressFlow']
67
69
  else:
68
- data_source = None
69
- if 'flowName' in context:
70
- flow_name = context['flowName']
71
- else:
72
- flow_name = None
73
- if 'flowId' in context:
74
- flow_id = context['flowId']
75
- else:
76
- flow_id = None
77
- if 'actionName' in context:
78
- action_name = context['actionName']
79
- else:
80
- action_name = None
81
- if 'actionId' in context:
82
- action_id = context['actionId']
83
- else:
84
- action_id = None
85
- if 'actionVersion' in context:
86
- action_version = context['actionVersion']
87
- else:
88
- action_version = None
89
- if 'hostname' in context:
90
- hostname = context['hostname']
91
- else:
92
- hostname = None
93
- if 'systemName' in context:
94
- system_name = context['systemName']
95
- else:
96
- system_name = None
70
+ egress_flow = None
71
+ system = context['systemName']
97
72
  if 'collect' in context:
98
73
  collect = context['collect']
99
74
  else:
@@ -106,21 +81,18 @@ class Context(NamedTuple):
106
81
  memo = context['memo']
107
82
  else:
108
83
  memo = None
109
-
110
84
  return Context(did=did,
111
- delta_file_name=delta_file_name,
112
- data_source=data_source,
113
- flow_name=flow_name,
114
- flow_id=flow_id,
85
+ action_flow=action_flow,
115
86
  action_name=action_name,
116
- action_id=action_id,
117
- action_version=action_version,
87
+ source_filename=source_filename,
88
+ ingress_flow=ingress_flow,
89
+ egress_flow=egress_flow,
90
+ system=system,
118
91
  hostname=hostname,
119
- system_name=system_name,
92
+ content_service=content_service,
120
93
  collect=collect,
121
94
  collected_dids=collected_dids,
122
95
  memo=memo,
123
- content_service=content_service,
124
96
  logger=logger)
125
97
 
126
98
 
@@ -225,6 +197,7 @@ class Content:
225
197
 
226
198
  return new_segments
227
199
 
200
+
228
201
  def get_size(self):
229
202
  """
230
203
  Returns the size of the content in bytes.
@@ -323,17 +296,41 @@ class Content:
323
296
  content_service=content_service)
324
297
 
325
298
 
299
+ class Domain(NamedTuple):
300
+ name: str
301
+ value: str
302
+ media_type: str
303
+
304
+ @classmethod
305
+ def from_dict(cls, domain: dict):
306
+ name = domain['name']
307
+ if 'value' in domain:
308
+ value = domain['value']
309
+ else:
310
+ value = None
311
+ media_type = domain['mediaType']
312
+ return Domain(name=name,
313
+ value=value,
314
+ media_type=media_type)
315
+
316
+
326
317
  class DeltaFileMessage(NamedTuple):
327
318
  metadata: Dict[str, str]
328
319
  content_list: List[Content]
320
+ domains: List[Domain]
321
+ enrichments: List[Domain]
329
322
 
330
323
  @classmethod
331
324
  def from_dict(cls, delta_file_message: dict, content_service: ContentService):
332
325
  metadata = delta_file_message['metadata']
333
326
  content_list = [Content.from_dict(content, content_service) for content in delta_file_message['contentList']]
327
+ domains = [Domain.from_dict(domain) for domain in delta_file_message['domains']] if 'domains' in delta_file_message else []
328
+ enrichments = [Domain.from_dict(domain) for domain in delta_file_message['enrichments']] if 'enrichments' in delta_file_message else []
334
329
 
335
330
  return DeltaFileMessage(metadata=metadata,
336
- content_list=content_list)
331
+ content_list=content_list,
332
+ domains=domains,
333
+ enrichments=enrichments)
337
334
 
338
335
 
339
336
  class Event(NamedTuple):
@@ -344,10 +341,9 @@ class Event(NamedTuple):
344
341
  return_address: str
345
342
 
346
343
  @classmethod
347
- def create(cls, event: dict, content_service: ContentService, logger: Logger):
348
- delta_file_messages = [DeltaFileMessage.from_dict(delta_file_message, content_service) for delta_file_message in
349
- event['deltaFileMessages']]
350
- context = Context.create(event['actionContext'], content_service, logger)
344
+ def create(cls, event: dict, hostname: str, content_service: ContentService, logger: Logger):
345
+ delta_file_messages = [DeltaFileMessage.from_dict(delta_file_message, content_service) for delta_file_message in event['deltaFileMessages']]
346
+ context = Context.create(event['actionContext'], hostname, content_service, logger)
351
347
  params = event['actionParams']
352
348
  queue_name = None
353
349
  if 'queueName' in event:
deltafi/exception.py CHANGED
@@ -23,6 +23,16 @@ class ExpectedContentException(RuntimeError):
23
23
  self.size = size
24
24
 
25
25
 
26
+ class MissingDomainException(RuntimeError):
27
+ def __init__(self, name):
28
+ self.name = name
29
+
30
+
31
+ class MissingEnrichmentException(RuntimeError):
32
+ def __init__(self, name):
33
+ self.name = name
34
+
35
+
26
36
  class MissingMetadataException(RuntimeError):
27
37
  def __init__(self, key):
28
38
  self.key = key
deltafi/input.py CHANGED
@@ -17,13 +17,172 @@
17
17
  #
18
18
 
19
19
  from deltafi.domain import *
20
- from deltafi.exception import MissingMetadataException, ExpectedContentException
20
+ from deltafi.exception import MissingMetadataException, ExpectedContentException, MissingDomainException, \
21
+ MissingEnrichmentException
22
+
23
+
24
+ class DomainInput(NamedTuple):
25
+ content: List[Content]
26
+ metadata: Dict[str, str]
27
+ domains: Dict[str, Domain]
28
+
29
+ def has_content(self) -> bool:
30
+ return len(self.content) > 0
31
+
32
+ def content_at(self, index: int) -> Content:
33
+ if len(self.content) < index + 1:
34
+ raise ExpectedContentException(index, len(self.content))
35
+ return self.content[index]
36
+
37
+ def first_content(self):
38
+ return self.content_at(0)
39
+
40
+ def get_metadata(self, key: str):
41
+ if key in self.metadata:
42
+ return self.metadata[key]
43
+ else:
44
+ raise MissingMetadataException(key)
45
+
46
+ def get_metadata_or_else(self, key: str, default: str) -> str:
47
+ if key in self.metadata:
48
+ return self.metadata[key]
49
+ else:
50
+ return default
51
+
52
+ def has_domain(self, name: str) -> bool:
53
+ return name in self.domains
54
+
55
+ def domain(self, name: str) -> Domain:
56
+ if not self.has_domain(name):
57
+ raise MissingDomainException(name)
58
+ return self.domains[name]
59
+
21
60
 
22
61
  class EgressInput(NamedTuple):
23
62
  content: Content
24
63
  metadata: dict
25
64
 
26
65
 
66
+ class EnrichInput(NamedTuple):
67
+ content: List[Content]
68
+ metadata: dict
69
+ domains: Dict[str, Domain]
70
+ enrichments: Dict[str, Domain]
71
+
72
+ def has_content(self) -> bool:
73
+ return len(self.content) > 0
74
+
75
+ def content_at(self, index: int) -> Content:
76
+ if len(self.content) < index + 1:
77
+ raise ExpectedContentException(index, len(self.content))
78
+ return self.content[index]
79
+
80
+ def first_content(self):
81
+ return self.content_at(0)
82
+
83
+ def get_metadata(self, key: str):
84
+ if key in self.metadata:
85
+ return self.metadata[key]
86
+ else:
87
+ raise MissingMetadataException(key)
88
+
89
+ def get_metadata_or_else(self, key: str, default: str) -> str:
90
+ if key in self.metadata:
91
+ return self.metadata[key]
92
+ else:
93
+ return default
94
+
95
+ def has_domain(self, name: str) -> bool:
96
+ return name in self.domains
97
+
98
+ def domain(self, name: str) -> Domain:
99
+ if not self.has_domain(name):
100
+ raise MissingDomainException(name)
101
+ return self.domains[name]
102
+
103
+ def has_enrichment(self, name: str) -> bool:
104
+ return name in self.enrichments
105
+
106
+ def enrichment(self, name: str) -> Domain:
107
+ if not self.has_enrichment(name):
108
+ raise MissingEnrichmentException(name)
109
+ return self.enrichments[name]
110
+
111
+
112
+ class FormatInput(NamedTuple):
113
+ content: List[Content]
114
+ metadata: dict
115
+ domains: Dict[str, Domain]
116
+ enrichments: Dict[str, Domain]
117
+
118
+ def has_content(self) -> bool:
119
+ return len(self.content) > 0
120
+
121
+ def content_at(self, index: int) -> Content:
122
+ if len(self.content) < index + 1:
123
+ raise ExpectedContentException(index, len(self.content))
124
+ return self.content[index]
125
+
126
+ def first_content(self):
127
+ return self.content_at(0)
128
+
129
+ def get_metadata(self, key: str):
130
+ if key in self.metadata:
131
+ return self.metadata[key]
132
+ else:
133
+ raise MissingMetadataException(key)
134
+
135
+ def get_metadata_or_else(self, key: str, default: str) -> str:
136
+ if key in self.metadata:
137
+ return self.metadata[key]
138
+ else:
139
+ return default
140
+
141
+ def has_domain(self, name: str) -> bool:
142
+ return name in self.domains
143
+
144
+ def domain(self, name: str) -> Domain:
145
+ if not self.has_domain(name):
146
+ raise MissingDomainException(name)
147
+ return self.domains[name]
148
+
149
+ def has_enrichment(self, name: str) -> bool:
150
+ return name in self.enrichments
151
+
152
+ def enrichment(self, name: str) -> Domain:
153
+ if not self.has_enrichment(name):
154
+ raise MissingEnrichmentException(name)
155
+ return self.enrichments[name]
156
+
157
+
158
+ class LoadInput(NamedTuple):
159
+ content: List[Content]
160
+ metadata: dict
161
+
162
+ def has_content(self) -> bool:
163
+ return len(self.content) > 0
164
+
165
+ def content_at(self, index: int) -> Content:
166
+ if len(self.content) < index + 1:
167
+ raise ExpectedContentException(index, len(self.content))
168
+ return self.content[index]
169
+
170
+ def first_content(self):
171
+ return self.content_at(0)
172
+
173
+ def get_metadata(self, key: str):
174
+ if key in self.metadata:
175
+ return self.metadata[key]
176
+ else:
177
+ raise MissingMetadataException(key)
178
+
179
+ def get_metadata_or_else(self, key: str, default: str) -> str:
180
+ if key in self.metadata:
181
+ return self.metadata[key]
182
+ else:
183
+ return default
184
+
185
+
27
186
  class TransformInput(NamedTuple):
28
187
  content: List[Content]
29
188
  metadata: dict
@@ -50,3 +209,8 @@ class TransformInput(NamedTuple):
50
209
  return self.metadata[key]
51
210
  else:
52
211
  return default
212
+
213
+
214
+ class ValidateInput(NamedTuple):
215
+ content: Content
216
+ metadata: dict
deltafi/plugin.py CHANGED
@@ -34,7 +34,8 @@ from importlib import metadata
34
34
  import requests
35
35
  from deltafi.actioneventqueue import ActionEventQueue
36
36
  from deltafi.domain import Event, ActionExecution
37
- from deltafi.exception import ExpectedContentException, MissingMetadataException
37
+ from deltafi.exception import ExpectedContentException, MissingDomainException, MissingEnrichmentException, \
38
+ MissingMetadataException
38
39
  from deltafi.logger import get_logger
39
40
  from deltafi.result import ErrorResult
40
41
  from deltafi.storage import ContentService
@@ -46,9 +47,9 @@ def _coordinates():
46
47
 
47
48
 
48
49
  def _setup_queue(max_connections):
49
- url = os.getenv('VALKEY_URL', 'http://deltafi-valkey-master:6379')
50
- password = os.getenv('VALKEY_PASSWORD')
51
- return ActionEventQueue(url, max_connections, password)
50
+ redis_url = os.getenv('REDIS_URL', 'http://deltafi-redis-master:6379')
51
+ password = os.getenv('REDIS_PASSWORD')
52
+ return ActionEventQueue(redis_url, max_connections, password)
52
53
 
53
54
 
54
55
  def _setup_content_service():
@@ -164,6 +165,8 @@ class Plugin(object):
164
165
  'name': self.action_name(action),
165
166
  'description': action.description,
166
167
  'type': action.action_type.name,
168
+ 'requiresDomains': action.requires_domains,
169
+ 'requiresEnrichments': action.requires_enrichments,
167
170
  'schema': action.param_class().model_json_schema()
168
171
  }
169
172
 
@@ -260,7 +263,7 @@ class Plugin(object):
260
263
  while True:
261
264
  try:
262
265
  event_string = self.queue.take(self.action_name(action))
263
- event = Event.create(json.loads(event_string), self.content_service, action_logger)
266
+ event = Event.create(json.loads(event_string), self.hostname, self.content_service, action_logger)
264
267
  start_time = time.time()
265
268
  action_logger.debug(f"Processing event for did {event.context.did}")
266
269
 
@@ -274,6 +277,14 @@ class Plugin(object):
274
277
  f"Action attempted to look up element {e.index + 1} (index {e.index}) from "
275
278
  f"content list of size {e.size}",
276
279
  f"{str(e)}\n{traceback.format_exc()}")
280
+ except MissingDomainException as e:
281
+ result = ErrorResult(event.context,
282
+ f"Action attempted to access domain {e.name}, which does not exist",
283
+ f"{str(e)}\n{traceback.format_exc()}")
284
+ except MissingEnrichmentException as e:
285
+ result = ErrorResult(event.context,
286
+ f"Action attempted to access enrichment {e.name}, which does not exist",
287
+ f"{str(e)}\n{traceback.format_exc()}")
277
288
  except MissingMetadataException as e:
278
289
  result = ErrorResult(event.context,
279
290
  f"Missing metadata with key {e.key}",
@@ -286,10 +297,7 @@ class Plugin(object):
286
297
 
287
298
  response = {
288
299
  'did': event.context.did,
289
- 'flowName': event.context.flow_name,
290
- 'flowId': event.context.flow_id,
291
- 'actionName': event.context.action_name,
292
- 'actionId': event.context.action_id,
300
+ 'action': event.context.action_flow + "." + event.context.action_name,
293
301
  'start': start_time,
294
302
  'stop': time.time(),
295
303
  'type': result.result_type,