|
| 1 | +package io.temporal.samples.workflowstreams; |
| 2 | + |
| 3 | +import io.temporal.client.WorkflowClient; |
| 4 | +import io.temporal.client.WorkflowOptions; |
| 5 | +import io.temporal.samples.workflowstreams.Shared.HubInput; |
| 6 | +import io.temporal.samples.workflowstreams.Shared.NewsEvent; |
| 7 | +import io.temporal.workflowstreams.TopicHandle; |
| 8 | +import io.temporal.workflowstreams.WorkflowStreamClient; |
| 9 | +import io.temporal.workflowstreams.WorkflowStreamItem; |
| 10 | +import io.temporal.workflowstreams.WorkflowStreamSubscription; |
| 11 | +import java.util.UUID; |
| 12 | + |
| 13 | +/** |
| 14 | + * Scenario 4: external (non-activity) publisher. The hub workflow does no work of its own; it just |
| 15 | + * hosts the stream. A separate process publishes news into it using the same client factory used to |
| 16 | + * subscribe, then signals the workflow to close. Here the publisher and a subscriber run as two |
| 17 | + * threads. |
| 18 | + */ |
| 19 | +public class ExternalPublisher { |
| 20 | + |
| 21 | + private static final String[] HEADLINES = { |
| 22 | + "markets open higher", "new bridge opens downtown", "local team wins championship", |
| 23 | + }; |
| 24 | + |
| 25 | + /** The sentinel the publisher sends last so the subscriber knows to stop. */ |
| 26 | + private static final String DONE_HEADLINE = "-- end of feed --"; |
| 27 | + |
| 28 | + public static void main(String[] args) throws InterruptedException { |
| 29 | + WorkflowClient client = Shared.newWorkflowClient(); |
| 30 | + |
| 31 | + String workflowId = "workflow-streams-hub-" + UUID.randomUUID(); |
| 32 | + HubWorkflow workflow = |
| 33 | + client.newWorkflowStub( |
| 34 | + HubWorkflow.class, |
| 35 | + WorkflowOptions.newBuilder() |
| 36 | + .setWorkflowId(workflowId) |
| 37 | + .setTaskQueue(Shared.TASK_QUEUE) |
| 38 | + .build()); |
| 39 | + WorkflowClient.start(workflow::host, new HubInput("newsroom")); |
| 40 | + System.out.println("Started workflow: " + workflowId); |
| 41 | + |
| 42 | + Thread subscriber = |
| 43 | + new Thread( |
| 44 | + () -> { |
| 45 | + try (WorkflowStreamClient stream = |
| 46 | + WorkflowStreamClient.newInstance(client, workflowId); |
| 47 | + WorkflowStreamSubscription subscription = |
| 48 | + stream.topic(Shared.TOPIC_NEWS).subscribe(0)) { |
| 49 | + for (WorkflowStreamItem item : subscription) { |
| 50 | + NewsEvent evt = Shared.decode(item, NewsEvent.class); |
| 51 | + if (evt.headline.equals(DONE_HEADLINE)) { |
| 52 | + return; |
| 53 | + } |
| 54 | + System.out.printf("[subscriber] %s%n", evt.headline); |
| 55 | + } |
| 56 | + } |
| 57 | + }); |
| 58 | + |
| 59 | + Thread publisher = |
| 60 | + new Thread( |
| 61 | + () -> { |
| 62 | + try (WorkflowStreamClient producer = |
| 63 | + WorkflowStreamClient.newInstance(client, workflowId)) { |
| 64 | + TopicHandle news = producer.topic(Shared.TOPIC_NEWS); |
| 65 | + for (String headline : HEADLINES) { |
| 66 | + news.publish(new NewsEvent(headline)); |
| 67 | + System.out.printf("[publisher] sent: %s%n", headline); |
| 68 | + try { |
| 69 | + Thread.sleep(500); |
| 70 | + } catch (InterruptedException e) { |
| 71 | + Thread.currentThread().interrupt(); |
| 72 | + return; |
| 73 | + } |
| 74 | + } |
| 75 | + // Force-flush the sentinel and wait for the server to confirm delivery |
| 76 | + // before signaling the workflow to close. |
| 77 | + news.publish(new NewsEvent(DONE_HEADLINE), /* forceFlush */ true); |
| 78 | + producer.flush(); |
| 79 | + } |
| 80 | + workflow.close(); |
| 81 | + System.out.println("[publisher] signaled close"); |
| 82 | + }); |
| 83 | + |
| 84 | + subscriber.start(); |
| 85 | + publisher.start(); |
| 86 | + subscriber.join(); |
| 87 | + publisher.join(); |
| 88 | + System.exit(0); |
| 89 | + } |
| 90 | +} |
0 commit comments