Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add simple examples of gem usage #20

Merged
merged 2 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ parent function.
```ruby
def create_build_and_test
UberTask.run(
name: "Build and Test"
"Build and Test"
default_retry_count: 1,
default_retry_wait: 5.mins,
retry_count: 1
Expand All @@ -73,7 +73,7 @@ On calling the `.run` method of UberTask inside this function, we add this funct

#### parameters

1. name:
1. name -
Default value is nil. Set the value of this parameter which
signifies what the function does.

Expand Down Expand Up @@ -107,7 +107,7 @@ We need to call this inside the `UberTask#run` method. This event is triggered w
```ruby
def install_ruby
UberTask.run(
name: "Install Ruby"
"Install Ruby"
retry_count: 2
) do

Expand Down Expand Up @@ -191,6 +191,14 @@ TODO: need to come up with an appropriate example.
1. block:
Pass a Ruby block that contains the code to be executed.

## Examples

You can run some examples at `examples/` folder:

```
ruby examples/download_and_move_file.rb
```

## License

The gem is available as open source under the terms of the
Expand Down
80 changes: 80 additions & 0 deletions examples/download_and_move_file.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# frozen_string_literal: true

require 'uber_task'
require 'colorize'

require_relative 'download_file'
require_relative 'move_file'

module Examples
class DownloadAndMoveFile
def self.run(source:, download_path:, move_path:)
UberTask.run('Download and move file', retry_count: 2) do
UberTask.on_success do
UberTask.logger.info(
'Top-level task was completed successfully!'.green,
)
end

UberTask.on_subtask_error do
UberTask.logger.info(
'Unexpected subtask error can be caught on top-level task ' \
'and an early return can be made, ' \
'isn\'t that cool!?'.underline,
)
return # Try to remove this line and see what happens!
Copy link
Member

@borela borela Jul 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the return, returns inside this block will affect the method that handles the exection.

We have to raise RetryTask, SkipTask or EventHandled, and if we don't raise either of these options, the exception will continue to bubble up.

It looks like I forgot to add a UberTask.event_handled method, add that method. All events have a .handled method already.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the return and added handling different types of exceptions which can be raised by subtasks

end

# Notice that we are passing `vital: true` option so that
# an early return can be made if task fails
begin
Examples::DownloadFile.run(
source: source,
to: download_path,
vital: true,
)
rescue StandardError => err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the error check inside on_subtask_error, which will show the main feature, centralized error reporting, and how the parent task can force a child task to skip or retry. Here's an example.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved error check to on_subtask_error

UberTask.logger.info "Failed to download file -- #{err.message}"
return
end

Examples::MoveFile.run(from: download_path, to: move_path)
end
end
end
end

if __FILE__ == $PROGRAM_NAME
Dir.mktmpdir do |dir|
download_path = File.join(dir, 'test')
move_path = File.join(dir, 'new_path')

puts '--- Running successfull case ---'
Examples::DownloadAndMoveFile.run(
source: VALID_FILE_URI,
download_path: download_path,
move_path: move_path,
)

puts "\n--- Running case which fails to download file ---\n"
Examples::DownloadAndMoveFile.run(
source: NON_EXESTENT_FILE_URI,
download_path: download_path,
move_path: move_path,
)

puts "\n--- Running case with invalid download path ---\n"
Examples::DownloadAndMoveFile.run(
source: VALID_FILE_URI,
download_path: '/invalid_path',
move_path: move_path,
)

puts "\n--- Running case with invalid move path ---\n"
Examples::DownloadAndMoveFile.run(
source: VALID_FILE_URI,
download_path: download_path,
move_path: '/invalid_path',
)
end
end
86 changes: 86 additions & 0 deletions examples/download_file.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# frozen_string_literal: true

require 'uber_task'
require 'colorize'
require 'open-uri'
require 'tmpdir'

VALID_FILE_URI = 'https://github.com/shakacode/uber_task/raw/main/README.md'
NON_EXESTENT_FILE_URI = 'https://github.com/shakacode/uber_task/raw/main/NON_EXISTENT.md'

module Examples
class DownloadFile
def self.run(to:, source: VALID_FILE_URI, **task_options)
UberTask.run(
'Download file from external source',
default_retry_wait: 3,
retry_count: 5,
vital: false,
**task_options,
) do
UberTask.on_retry do
UberTask.logger.info(
"Retrying to download file from #{source}...".yellow,
)
end

UberTask.on_success do
UberTask.logger.info(
"Downloaded file #{source} and saved it at #{to}".green,
)
end

save_external_file!(source: source, to: to)
end
end

def self.save_external_file!(source:, to:)
URI.parse(source).open { |io| File.write(to, io.read) }
rescue OpenURI::HTTPError => err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this check to the parent task on_subtask_error; all errors bubble up to the parent, like in Javascript and if the parent asks the task to be retried, the current task (child) will run again.

This was the main idea to deploy apps on popmenu, we have a single place for common network errors and tasks can have many subtasks but all of them have common network errors and each time they happen, the on_subtask_error of the top task checks the error type and just ask to retry.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved rescue from here to parent task's on_subtask_error

raise UberTask::RetryTask.new(reason: err.message)
end
private_class_method :save_external_file!
end
end

if __FILE__ == $PROGRAM_NAME
Dir.mktmpdir do |dir|
filepath = File.join(dir, 'test')

puts '--- Running successfull case ---'
Examples::DownloadFile.run(source: VALID_FILE_URI, to: filepath)

puts "\n--- Running failing case with `vital: true`---\n"
begin
Examples::DownloadFile.run(
source: NON_EXESTENT_FILE_URI,
to: filepath,
vital: true,
)
rescue StandardError
UberTask.logger.info 'Error was raised'.red
end

puts "\n--- Running failing case with `vital: false`---\n"
Examples::DownloadFile.run(
source: NON_EXESTENT_FILE_URI,
to: filepath,
vital: false,
)
UberTask.logger.info 'Error wasn\'t raised'.green

puts "\n--- Running failing case with `retry_count: 1`---\n"
Examples::DownloadFile.run(
source: NON_EXESTENT_FILE_URI,
to: filepath,
retry_count: 1,
)

puts "\n--- Running failing case with `default_retry_wait: 0`---\n"
Examples::DownloadFile.run(
source: NON_EXESTENT_FILE_URI,
to: filepath,
default_retry_wait: 0,
)
end
end
84 changes: 84 additions & 0 deletions examples/move_file.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# frozen_string_literal: true

require 'uber_task'
require 'colorize'
require 'tmpdir'
require 'fileutils'

module Examples
class MoveFile
def self.run(from:, to:, **task_options)
UberTask.run(
'Download file from external source',
default_retry_wait: 1,
retry_count: 3,
vital: false,
**task_options,
) do
UberTask.on_success do
UberTask.logger.info "Moved file from #{from} to #{to}".green
end

UberTask.on_retry do
UberTask.logger.info(
"Retrying to move file from #{from} to #{to}...".yellow,
)
end

move_file!(from: from, to: to)
end
end

def self.move_file!(from:, to:)
FileUtils.mv(from, to)
rescue Errno::ENOENT => err
raise UberTask::RetryTask.new(reason: err.message)
end
private_class_method :move_file!
end
end

if __FILE__ == $PROGRAM_NAME
Dir.mktmpdir do |dir|
File.open(File.join(dir, 'old_path'), 'w') do |file|
file.write('test')

puts '--- Running successfull case ---'
Examples::MoveFile.run(from: file.path, to: File.join(dir, 'new_path'))
end

### Notice that task has `vital: true` so error is raised
puts "\n--- Running failing case with `vital: true`---\n"
begin
Examples::MoveFile.run(
from: 'invalid_path',
to: File.join(dir, 'new_path'),
vital: true,
)
rescue StandardError
UberTask.logger.info 'Error was raised'.red
end

### Notice that task has `vital: false` so error isn't raised
puts "\n--- Running failing case with `vital: false`---\n"
Examples::MoveFile.run(
from: 'invalid_path',
to: File.join(dir, 'new_path'),
vital: false,
)

puts "\n--- Running failing case with `retry_count: 1`---\n"
Examples::MoveFile.run(
from: 'invalid_path',
to: File.join(dir, 'new_path'),
retry_count: 1,
)

puts "\n--- Running failing case with `default_retry_wait: 3`---\n"
Examples::MoveFile.run(
from: 'invalid_path',
to: File.join(dir, 'new_path'),
default_retry_wait: 3,
)
end
end