Skip to content

Commit ec6cb7e

Browse files
add frequent polling sample
1 parent 6788b0e commit ec6cb7e

7 files changed

Lines changed: 183 additions & 0 deletions

File tree

polling/frequent/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Frequent Polling Activity
2+
3+
This sample demonstrates how to implement a frequent polling mechanism
4+
(1 second or faster) inside an Activity.
5+
The implementation is a loop that polls a service and then sleeps for the poll
6+
interval (1 second in the sample).
7+
8+
## How to Run
9+
10+
1. **Start the Worker:**
11+
12+
Open a terminal and run the following command to start the worker process.
13+
The worker will listen for tasks on the `frequent-polling-sample` task queue.
14+
15+
```bash
16+
bundle exec ruby worker.rb
17+
```
18+
19+
You will see the worker log messages indicating it is calling the service.
20+
It will try several times, with a short delay between each attempt.
21+
22+
2. **Start the Workflow:**
23+
24+
In a separate terminal, run this command to start the workflow.
25+
This script will start the workflow and wait for its completion,
26+
printing the final result.
27+
28+
```bash
29+
bundle exec ruby starter.rb
30+
```
31+
32+
After a few seconds, the service will succeed.
33+
You will see the final result printed in the starter's terminal,
34+
and the worker will log the successful completion.
35+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# frozen_string_literal: true
2+
3+
require 'temporalio/activity'
4+
require_relative 'test_service'
5+
6+
module Polling
7+
module Frequent
8+
class ComposeGreetingActivity < Temporalio::Activity::Definition
9+
def execute(input)
10+
loop do
11+
activity_info = Temporalio::Activity::Context.current.info
12+
begin
13+
return TestService.get_service_result(input, activity_info)
14+
rescue TestService::TestServiceError
15+
Temporalio::Activity::Context.current.logger.info('Test service was down')
16+
end
17+
Temporalio::Activity::Context.current.heartbeat
18+
sleep 1
19+
end
20+
end
21+
end
22+
end
23+
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# frozen_string_literal: true
2+
3+
require 'temporalio/workflow'
4+
require_relative 'compose_greeting_activity'
5+
6+
module Polling
7+
module Frequent
8+
class GreetingWorkflow < Temporalio::Workflow::Definition
9+
def execute(name)
10+
Temporalio::Workflow.execute_activity(
11+
ComposeGreetingActivity,
12+
{ greeting: 'Hello', name: name },
13+
start_to_close_timeout: 60,
14+
heartbeat_timeout: 2
15+
)
16+
end
17+
end
18+
end
19+
end

polling/frequent/starter.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
require 'temporalio/client'
4+
require_relative 'greeting_workflow'
5+
6+
# Create a client
7+
client = Temporalio::Client.connect('localhost:7233', 'default')
8+
9+
# Run workflow
10+
puts 'Executing workflow'
11+
result = client.execute_workflow(
12+
Polling::Frequent::GreetingWorkflow,
13+
'World',
14+
id: "frequent-polling-sample-workflow-id-#{Time.now.to_i}",
15+
task_queue: 'frequent-polling-sample'
16+
)
17+
puts "Workflow result: #{result}"

polling/frequent/test_service.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# frozen_string_literal: true
2+
3+
module Polling
4+
module Frequent
5+
# A mock external service with simulated errors.
6+
module TestService
7+
class TestServiceError < StandardError; end
8+
9+
@attempts = Hash.new(0)
10+
ERROR_ATTEMPTS = 5
11+
12+
def get_service_result(input, activity_info)
13+
workflow_id = activity_info.workflow_id
14+
@attempts[workflow_id] ||= 0
15+
@attempts[workflow_id] += 1
16+
17+
# Fake delay to simulate service call
18+
sleep 0.01
19+
puts "Attempt #{@attempts[workflow_id]} of #{ERROR_ATTEMPTS} to invoke service"
20+
21+
raise TestServiceError, 'service is down' unless @attempts[workflow_id] == ERROR_ATTEMPTS
22+
23+
"#{input['greeting']}, #{input['name']}!"
24+
end
25+
module_function :get_service_result
26+
end
27+
end
28+
end

polling/frequent/worker.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# frozen_string_literal: true
2+
3+
require_relative 'greeting_workflow'
4+
require_relative 'compose_greeting_activity'
5+
require 'temporalio/client'
6+
require 'temporalio/worker'
7+
8+
# Create a client
9+
client = Temporalio::Client.connect('localhost:7233', 'default')
10+
11+
worker = Temporalio::Worker.new(
12+
client:,
13+
task_queue: 'frequent-polling-sample',
14+
workflows: [Polling::Frequent::GreetingWorkflow],
15+
activities: [Polling::Frequent::ComposeGreetingActivity]
16+
)
17+
18+
puts 'Starting worker (ctrl+c to exit)'
19+
worker.run(shutdown_signals: ['SIGINT'])
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# frozen_string_literal: true
2+
3+
require 'test'
4+
require 'securerandom'
5+
require 'temporalio/testing'
6+
require 'temporalio/worker'
7+
require 'polling/frequent/greeting_workflow'
8+
require 'polling/frequent/compose_greeting_activity'
9+
require 'polling/frequent/test_service'
10+
11+
module Polling
12+
module Frequent
13+
class GreetingWorkflowTest < Test
14+
def test_workflow_completes_after_polling
15+
# skip_if_not_x86!
16+
task_queue = "tq-#{SecureRandom.uuid}"
17+
18+
Temporalio::Testing::WorkflowEnvironment.start_local do |env|
19+
worker = Temporalio::Worker.new(
20+
client: env.client,
21+
task_queue: task_queue,
22+
activities: [Polling::Frequent::ComposeGreetingActivity],
23+
workflows: [Polling::Frequent::GreetingWorkflow]
24+
)
25+
26+
handle = env.client.start_workflow(
27+
Polling::Frequent::GreetingWorkflow,
28+
'Temporal',
29+
id: "wf-#{SecureRandom.uuid}",
30+
task_queue: task_queue
31+
)
32+
33+
worker.run do
34+
# Wait for the workflow to complete and assert its result
35+
result = handle.result
36+
assert_equal('Hello, Temporal!', result)
37+
end
38+
end
39+
end
40+
end
41+
end
42+
end

0 commit comments

Comments
 (0)