Skip to content

Commit 16e719b

Browse files
gecage952Lance-Drane
authored andcommitted
Add initial example for service to service communication
1 parent 97fa171 commit 16e719b

File tree

6 files changed

+226
-0
lines changed

6 files changed

+226
-0
lines changed

examples/4_service_to_service/__init__.py

Whitespace-only changes.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"""First Service for example. Sends a message to service two and emits an event for the client."""
2+
3+
import logging
4+
5+
from intersect_sdk import (
6+
HierarchyConfig,
7+
IntersectBaseCapabilityImplementation,
8+
IntersectDirectMessageParams,
9+
IntersectEventDefinition,
10+
IntersectService,
11+
IntersectServiceConfig,
12+
default_intersect_lifecycle_loop,
13+
intersect_event,
14+
intersect_message,
15+
intersect_status,
16+
)
17+
18+
logging.basicConfig(level=logging.INFO)
19+
logger = logging.getLogger(__name__)
20+
21+
22+
class ExampleServiceOneCapabilityImplementation(IntersectBaseCapabilityImplementation):
23+
"""Service One Capability."""
24+
25+
@intersect_status()
26+
def status(self) -> str:
27+
"""Basic status function which returns a hard-coded string."""
28+
return 'Up'
29+
30+
@intersect_message()
31+
def pass_text_to_service_2(self, text: str) -> None:
32+
"""Takes in a string parameter and sends it to service 2."""
33+
logger.info('maing it to service one')
34+
msg_to_send = IntersectDirectMessageParams(
35+
destination='example-organization.example-facility.example-system.example-subsystem.service-two',
36+
operation='ServiceTwo.test_service',
37+
payload=text,
38+
)
39+
40+
# Send intersect message to another service
41+
self.intersect_sdk_call_service(msg_to_send, self.service_2_handler)
42+
43+
@intersect_event(events={'response_event': IntersectEventDefinition(event_type=str)})
44+
def service_2_handler(self, msg: str) -> None:
45+
"""Handles response from service two and emites the response as an event for the client."""
46+
logger.info('maing it to right before emitting event')
47+
self.intersect_sdk_emit_event('response_event', f'Received Response from Service 2: {msg}')
48+
49+
50+
if __name__ == '__main__':
51+
from_config_file = {
52+
'brokers': [
53+
{
54+
'username': 'intersect_username',
55+
'password': 'intersect_password',
56+
'port': 1883,
57+
'protocol': 'mqtt3.1.1',
58+
},
59+
],
60+
}
61+
config = IntersectServiceConfig(
62+
hierarchy=HierarchyConfig(
63+
organization='example-organization',
64+
facility='example-facility',
65+
system='example-system',
66+
subsystem='example-subsystem',
67+
service='service-one',
68+
),
69+
status_interval=30.0,
70+
**from_config_file,
71+
)
72+
capability = ExampleServiceOneCapabilityImplementation()
73+
capability.capability_name = 'ServiceOne'
74+
service = IntersectService([capability], config)
75+
logger.info('Starting service one, use Ctrl+C to exit.')
76+
default_intersect_lifecycle_loop(
77+
service,
78+
)
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"""Second Service for example."""
2+
3+
import logging
4+
5+
from intersect_sdk import (
6+
HierarchyConfig,
7+
IntersectBaseCapabilityImplementation,
8+
IntersectService,
9+
IntersectServiceConfig,
10+
default_intersect_lifecycle_loop,
11+
intersect_message,
12+
intersect_status,
13+
)
14+
15+
logging.basicConfig(level=logging.INFO)
16+
logger = logging.getLogger(__name__)
17+
18+
19+
class ExampleServiceTwoCapabilityImplementation(IntersectBaseCapabilityImplementation):
20+
"""Service Two Capability."""
21+
22+
@intersect_status()
23+
def status(self) -> str:
24+
"""Basic status function which returns a hard-coded string."""
25+
return 'Up'
26+
27+
@intersect_message
28+
def test_service(self, text: str) -> str:
29+
"""Returns the text given along with acknowledgement."""
30+
logger.info('Making it to service 2')
31+
return f'Acknowledging service one text -> {text}'
32+
33+
34+
if __name__ == '__main__':
35+
from_config_file = {
36+
'brokers': [
37+
{
38+
'username': 'intersect_username',
39+
'password': 'intersect_password',
40+
'port': 1883,
41+
'protocol': 'mqtt3.1.1',
42+
},
43+
],
44+
}
45+
config = IntersectServiceConfig(
46+
hierarchy=HierarchyConfig(
47+
organization='example-organization',
48+
facility='example-facility',
49+
system='example-system',
50+
subsystem='example-subsystem',
51+
service='service-two',
52+
),
53+
status_interval=30.0,
54+
**from_config_file,
55+
)
56+
capability = ExampleServiceTwoCapabilityImplementation()
57+
capability.capability_name = 'ServiceTwo'
58+
service = IntersectService([capability], config)
59+
logger.info('Starting service two, use Ctrl+C to exit.')
60+
default_intersect_lifecycle_loop(
61+
service,
62+
)
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"""Client for service to service example.
2+
3+
Kicks off exmaple by sending message to service one, and then
4+
waits for an event from service one to confirm the messages were passed between the two services properly.
5+
6+
"""
7+
8+
import logging
9+
10+
from intersect_sdk import (
11+
INTERSECT_JSON_VALUE,
12+
IntersectClient,
13+
IntersectClientCallback,
14+
IntersectClientConfig,
15+
IntersectDirectMessageParams,
16+
default_intersect_lifecycle_loop,
17+
)
18+
19+
logging.basicConfig(level=logging.INFO)
20+
logger = logging.getLogger(__name__)
21+
22+
23+
class SampleOrchestrator:
24+
"""Simply contains an event callback for events from Service One."""
25+
26+
def event_callback(
27+
self, _source: str, _operation: str, _event_name: str, payload: INTERSECT_JSON_VALUE
28+
) -> None:
29+
"""This simply prints the event from Service One to your console.
30+
31+
Params:
32+
source: the source of the response message.
33+
operation: the name of the function we called in the original message.
34+
_has_error: Boolean value which represents an error.
35+
payload: Value of the response from the Service.
36+
"""
37+
logger.info('making it to event callback')
38+
print(payload)
39+
40+
41+
if __name__ == '__main__':
42+
from_config_file = {
43+
'brokers': [
44+
{
45+
'username': 'intersect_username',
46+
'password': 'intersect_password',
47+
'port': 1883,
48+
'protocol': 'mqtt3.1.1',
49+
},
50+
],
51+
}
52+
53+
# The counter will start after the initial message.
54+
# If the service is already active and counting, this may do nothing.
55+
initial_messages = [
56+
IntersectDirectMessageParams(
57+
destination='example-organization.example-facility.example-system.example-subsystem.service-one',
58+
operation='ServiceOne.pass_text_to_service_2',
59+
payload='Kicking off the example!',
60+
)
61+
]
62+
config = IntersectClientConfig(
63+
initial_message_event_config=IntersectClientCallback(
64+
messages_to_send=initial_messages,
65+
services_to_start_listening_for_events=[
66+
'example-organization.example-facility.example-system.example-subsystem.service-one'
67+
],
68+
),
69+
**from_config_file,
70+
)
71+
orchestrator = SampleOrchestrator()
72+
client = IntersectClient(
73+
config=config,
74+
event_callback=orchestrator.event_callback,
75+
)
76+
default_intersect_lifecycle_loop(
77+
client,
78+
)

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ test = [
6363
test-all = "pytest tests/ --cov=src/intersect_sdk/ --cov-fail-under=80 --cov-report=html:reports/htmlcov/ --cov-report=xml:reports/coverage_report.xml --junitxml=reports/junit.xml"
6464
test-all-debug = "pytest tests/ --cov=src/intersect_sdk/ --cov-fail-under=80 --cov-report=html:reports/htmlcov/ --cov-report=xml:reports/coverage_report.xml --junitxml=reports/junit.xml -s"
6565
test-unit = "pytest tests/unit --cov=src/intersect_sdk/"
66+
test-e2e = "pytest tests/e2e --cov=src/intersect_sdk/"
6667
lint = {composite = ["lint-format", "lint-ruff", "lint-mypy"]}
6768
lint-format = "ruff format"
6869
lint-ruff = "ruff check --fix"

tests/e2e/test_examples.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,10 @@ def test_example_3_ping_pong_events():
132132

133133
def test_example_3_ping_pong_events_amqp():
134134
assert run_example_test('3_ping_pong_events_amqp') == 'ping\npong\nping\npong\n'
135+
136+
137+
def test_example_4_service_to_service():
138+
assert (
139+
run_example_test('4_service_to_service')
140+
== 'Received Response from Service 2: Acknowledging service one text -> Kicking off the example!'
141+
)

0 commit comments

Comments
 (0)