delayer-deferred-1.0.3/0000755000175000017500000000000012615150722012773 5ustar daidaidelayer-deferred-1.0.3/metadata.yml0000644000175000017500000000577312615150722015312 0ustar daidai--- !ruby/object:Gem::Specification name: delayer-deferred version: !ruby/object:Gem::Version version: 1.0.3 platform: ruby authors: - Toshiaki Asai autorequire: bindir: bin cert_chain: [] date: 2015-10-17 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: delayer requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 0.0.2 - - "<" - !ruby/object:Gem::Version version: '0.1' type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 0.0.2 - - "<" - !ruby/object:Gem::Version version: '0.1' - !ruby/object:Gem::Dependency name: bundler requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '1.7' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '1.7' - !ruby/object:Gem::Dependency name: rake requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '10.0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '10.0' - !ruby/object:Gem::Dependency name: minitest requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '5.7' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '5.7' description: Deferred for Delayer. email: - toshi.alternative@gmail.com executables: [] extensions: [] extra_rdoc_files: [] files: - ".gitignore" - Gemfile - LICENSE.txt - README.md - Rakefile - delayer-deferred.gemspec - lib/delayer/deferred.rb - lib/delayer/deferred/deferred.rb - lib/delayer/deferred/deferredable.rb - lib/delayer/deferred/enumerable.rb - lib/delayer/deferred/enumerator.rb - lib/delayer/deferred/thread.rb - lib/delayer/deferred/tools.rb - lib/delayer/deferred/version.rb - test/deferred_test.rb - test/enumerable_test.rb - test/helper.rb - test/testutils.rb - test/thread_test.rb homepage: '' licenses: - MIT metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 2.0.0 required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.4.5.1 signing_key: specification_version: 4 summary: Deferred for Delayer test_files: - test/deferred_test.rb - test/enumerable_test.rb - test/helper.rb - test/testutils.rb - test/thread_test.rb has_rdoc: delayer-deferred-1.0.3/test/0000755000175000017500000000000012615150722013752 5ustar daidaidelayer-deferred-1.0.3/test/thread_test.rb0000644000175000017500000000515712615150722016615 0ustar daidai# -*- coding: utf-8 -*- require_relative 'helper' describe(Thread) do include TestUtils before do Delayer.default = Delayer.generate_class end it "defer with Deferred#next" do thread = succeed = result = false uuid = SecureRandom.uuid eval_all_events do Thread.new { thread = true uuid }.next do |param| succeed = true result = param end end assert thread, "Thread did not executed." assert succeed, "next block did not executed." assert_equal uuid, result end it "defer with another Delayer" do thread = succeed = failure = result = false uuid = SecureRandom.uuid delayer = Delayer.generate_class eval_all_events(delayer) do delayer.Deferred.Thread.new { thread = true uuid }.next{ |param| succeed = true result = param }.trap{ |exception| failure = exception } end assert_equal false, failure assert thread, "Thread did not executed." assert succeed, "next block did not executed." assert_equal uuid, result end it "error handling" do delayer = Delayer.generate_class succeed = failure = recover = false uuid = SecureRandom.uuid eval_all_events(delayer) do delayer.Deferred.Thread.new { Delayer::Deferred.fail(uuid) }.next { succeed = true }.trap { |value| failure = value }.next { recover = true } end refute succeed, "Raised exception but it was executed successed route." assert_equal uuid, failure, "trap block takes incorrect value" assert recover, "next block did not executed when after trap" end it "exception handling" do succeed = failure = recover = false delayer = Delayer.generate_class eval_all_events(delayer) do delayer.Deferred.Thread.new { raise 'error test' }.next { succeed = true }.trap { failure = true }.next { recover = true } end refute succeed, "Raised exception but it was executed successed route." assert failure, "trap block did not executed" assert recover, "next block did not executed when after trap" end it "wait end of Deferredable if Deferredable block returns Thread" do result = failure = false delayer = Delayer.generate_class uuid = SecureRandom.uuid eval_all_events(delayer) do delayer.Deferred.new.next{ delayer.Deferred.Thread.new{ uuid } }.next{ |value| result = value }.trap{ |exception| failure = exception } end assert_equal uuid, result assert_equal false, failure end end delayer-deferred-1.0.3/test/testutils.rb0000644000175000017500000000036512615150722016343 0ustar daidaimodule TestUtils def eval_all_events(delayer=Delayer) native = Thread.list result = yield if block_given? while not(delayer.empty? and (Thread.list - native).empty?) delayer.run Thread.pass end result end end delayer-deferred-1.0.3/test/helper.rb0000644000175000017500000000024412615150722015556 0ustar daidairequire 'bundler/setup' require 'minitest/autorun' require 'delayer/deferred' require 'securerandom' require 'set' require 'timeout' require_relative 'testutils' delayer-deferred-1.0.3/test/enumerable_test.rb0000644000175000017500000000264612615150722017465 0ustar daidai# -*- coding: utf-8 -*- require_relative 'helper' describe(Enumerable) do include TestUtils before do @delayer = Delayer.generate_class end describe "deach" do it "iterate Array" do sum = 0 eval_all_events(@delayer) do (1..10000).to_a.deach(@delayer) do |digit| sum += digit end end assert_equal 50005000, sum end it "iterate infinite Enumerator" do log = [] finish = failure = nil @delayer = Delayer.generate_class(expire: 0.1) fib = Enumerator.new do |yielder| a = 1 b = 1 loop do c = a + b yielder << a a, b = b, c end end timeout(1) { fib.deach(@delayer) {|digit| log << digit }.next{ finish = true }.trap {|exception| failure = exception } @delayer.run } refute failure refute finish, "Enumerable#deach won't call next block" refute log.empty?, "Executed deach block" log_size = log.size sample_size = [156, log_size].min assert_equal fib.take(sample_size), log.take(sample_size), "deach block takes collect arguments" @delayer.run refute failure refute finish, "Enumerable#deach won't call next block" assert log.size > log_size, "Restart iteration if call Delayer#run (first #{log_size} iterations, second #{log.size})" end end end delayer-deferred-1.0.3/test/deferred_test.rb0000644000175000017500000001563512615150722017130 0ustar daidai# -*- coding: utf-8 -*- require_relative 'helper' describe(Delayer::Deferred) do include TestUtils before do Delayer.default = Delayer.generate_class end it "defer with Deferred#next" do succeed = failure = false eval_all_events do Delayer::Deferred::Deferred.new.next{ succeed = true }.trap{ |exception| failure = exception } end assert_equal false, failure assert succeed, "Deferred did not executed." end it "defer with another Delayer" do succeed = failure = false delayer = Delayer.generate_class eval_all_events(delayer) do delayer.Deferred.new.next { succeed = true }.trap{ |exception| failure = exception } end assert_equal false, failure assert succeed, "Deferred did not executed." end it "error handling" do succeed = failure = recover = false uuid = SecureRandom.uuid eval_all_events do Delayer::Deferred::Deferred.new.next { Delayer::Deferred.fail(uuid) }.next { succeed = true }.trap { |value| failure = value }.next { recover = true } end refute succeed, "Raised exception but it was executed successed route." assert_equal uuid, failure, "trap block takes incorrect value" assert recover, "next block did not executed when after trap" end it "exception handling" do succeed = failure = recover = false eval_all_events do Delayer::Deferred::Deferred.new.next { raise 'error test' }.next { succeed = true }.trap { failure = true }.next { recover = true } end refute succeed, "Raised exception but it was executed successed route." assert failure, "trap block did not executed" assert recover, "next block did not executed when after trap" end it "wait end of Deferredable if Deferredable block returns Deferredable" do result = failure = false delayer = Delayer.generate_class uuid = SecureRandom.uuid eval_all_events(delayer) do delayer.Deferred.new.next{ delayer.Deferred.new.next{ uuid } }.next{ |value| result = value }.trap{ |exception| failure = exception } end assert_equal uuid, result assert_equal false, failure end it "join Deferredable#next after end of previous Deferredable" do succeed = failure = false delayer = Delayer.generate_class deferredable = eval_all_events(delayer) do delayer.Deferred.new.next { true } end eval_all_events(delayer) do deferredable.next{ |value| succeed = value }.trap{ |exception| failure = exception } end assert_equal false, failure assert succeed, "Deferred did not executed." end describe "Deferred.when" do it "give 3 deferred" do result = failure = false delayer = Delayer.generate_class eval_all_events(delayer) do delayer.Deferred.when( delayer.Deferred.new.next{ 1 }, delayer.Deferred.new.next{ 2 }, delayer.Deferred.new.next{ 3 } ).next{ |values| result = values }.trap{ |exception| failure = exception } end assert_equal false, failure assert_equal [1,2,3], result end it "default deferred" do result = failure = false eval_all_events do Delayer::Deferred::Deferred.when( Delayer::Deferred::Deferred.new.next{ 1 }, Delayer::Deferred::Deferred.new.next{ 2 }, Delayer::Deferred::Deferred.new.next{ 3 } ).next{ |values| result = values }.trap{ |exception| failure = exception } end assert_equal false, failure assert_equal [1,2,3], result end it "give that is not Deferredable" do result = failure = false delayer = Delayer.generate_class assert_raises(TypeError) do eval_all_events(delayer) do delayer.Deferred.when( delayer.Deferred.new.next{ 1 }, 2, delayer.Deferred.new.next{ 3 } ).next{ |values| result = values }.trap{ |exception| failure = exception } end end assert_equal false, failure assert_equal false, result end it "execute trap block if failed" do result = failure = false delayer = Delayer.generate_class eval_all_events(delayer) do delayer.Deferred.when( delayer.Deferred.new.next{ 1 }, delayer.Deferred.new.next{ raise }, delayer.Deferred.new.next{ 3 } ).next{ |values| result = values }.trap{ |exception| failure = exception } end assert_kind_of RuntimeError, failure assert_equal false, result end it "no deferred given" do result = failure = false delayer = Delayer.generate_class eval_all_events(delayer) do delayer.Deferred.when().next{ |values| result = values }.trap{ |exception| failure = exception } end assert_equal false, failure assert_empty result end it "no deferred given for default delayer" do result = failure = false eval_all_events do Delayer::Deferred::Deferred.when().next{ |values| result = values }.trap{ |exception| failure = exception } end assert_equal false, failure assert_empty result end it "no deferred given for delayer module" do result = failure = false eval_all_events do Delayer::Deferred.when().next{ |values| result = values }.trap{ |exception| failure = exception } end assert_equal false, failure assert_empty result end end describe "cancel" do it "stops deferred chain" do succeed = failure = false delayer = Delayer.generate_class eval_all_events(delayer) do delayer.Deferred.new.next { succeed = true }.trap{ |exception| failure = exception }.cancel end assert_equal false, failure assert_equal false, succeed, "Deferred executed." end end describe "Deferredable#system" do it "command successed" do succeed = failure = false delayer = Delayer.generate_class eval_all_events(delayer) do delayer.Deferred.system("ruby", "-e", "exit 0").next{ |value| succeed = value }.trap{ |exception| failure = exception } end assert_equal false, failure assert succeed, "next block called" end it "command failed" do succeed = failure = false delayer = Delayer.generate_class eval_all_events(delayer) do delayer.Deferred.system("ruby", "-e", "exit 1").next{ |value| succeed = value }.trap{ |exception| failure = exception } end refute succeed, "next block did not called" assert failure.exited?, "command exited" assert_equal 1, failure.exitstatus, "command exit status is 1" end end end delayer-deferred-1.0.3/lib/0000755000175000017500000000000012615150722013541 5ustar daidaidelayer-deferred-1.0.3/lib/delayer/0000755000175000017500000000000012615150722015166 5ustar daidaidelayer-deferred-1.0.3/lib/delayer/deferred/0000755000175000017500000000000012615150722016746 5ustar daidaidelayer-deferred-1.0.3/lib/delayer/deferred/version.rb0000644000175000017500000000010112615150722020750 0ustar daidaimodule Delayer module Deferred VERSION = "1.0.3" end end delayer-deferred-1.0.3/lib/delayer/deferred/tools.rb0000644000175000017500000000357212615150722020442 0ustar daidai# -*- coding: utf-8 -*- module Delayer::Deferred module Tools def next(&proc) new.next(&proc) end def trap(&proc) new.trap(&proc) end # 実行中のDeferredを失敗させる。raiseと違って、Exception以外のオブジェクトをtrap()に渡すことができる。 # Deferredのnextとtrapの中でだけ呼び出すことができる。 # ==== Args # [value] trap()に渡す値 # ==== Throw # :__deferredable_fail をthrowする def fail(value) throw(:__deferredable_fail, value) end # 複数のdeferredを引数に取って、それら全ての実行が終了したら、 # その結果を引数の順番通りに格納したArrayを引数に呼ばれるDeferredを返す。 # 引数のDeferredが一つでも失敗するとこのメソッドの返すDeferredも失敗する。 # ==== Args # [*args] 終了を待つDeferredオブジェクト # ==== Return # Deferred def when(*args) return self.next{[]} if args.empty? defer, *follow = args raise TypeError, "Argument of Deferred.when must be Delayer::Deferred::Deferredable" unless defer.is_a? Delayer::Deferred::Deferredable if follow.empty? defer.next{|res| [res] } else remain = self.when(*follow) defer.next do |res| remain.next do |follow_res| follow_res.unshift(res) end end end end # Kernel#systemを呼び出して、コマンドが成功たら成功するDeferredを返す。 # 失敗した場合、trap{}ブロックには $? の値(Process::Status)か、例外が発生した場合それが渡される # ==== Args # [*args] Kernel#system の引数 # ==== Return # Deferred def system(*args) delayer.Deferred.Thread.new do if Kernel.system(*args) $? else delayer.Deferred.fail($?) end end end end end delayer-deferred-1.0.3/lib/delayer/deferred/thread.rb0000644000175000017500000000150312615150722020541 0ustar daidai# -*- coding: utf-8 -*- require "delayer" require "delayer/deferred/deferredable" class Thread include ::Delayer::Deferred::Deferredable def self.delayer Delayer end alias _deferredable_trap initialize def initialize(*args, &proc) _deferredable_trap(*args, &_deferredable_trap_proc(&proc)) end alias :deferredable_cancel :cancel def cancel deferredable_cancel kill end private def _deferredable_trap_proc proc = Proc.new ->(*args) do catch(:__deferredable_success) do failed = catch(:__deferredable_fail) do begin result = proc.call(*args) self.call(result) result rescue Exception => exception self.fail(exception) end throw :__deferredable_success end self.fail(failed) end end end end delayer-deferred-1.0.3/lib/delayer/deferred/enumerator.rb0000644000175000017500000000055012615150722021454 0ustar daidai# -*- coding: utf-8 -*- require "delayer" require "delayer/deferred/deferred" class Enumerator def deach(delayer=Delayer, &proc) delayer.Deferred.new.next do begin loop do proc.call(self.next()) if delayer.expire? break deach(delayer, &proc) end end rescue StopIteration nil end end end end delayer-deferred-1.0.3/lib/delayer/deferred/enumerable.rb0000644000175000017500000000046712615150722021421 0ustar daidai# -*- coding: utf-8 -*- require "delayer" require "delayer/deferred/enumerator" module Enumerable # 遅延each。あとで実行されるし、あんまりループに時間がかかるようなら一旦ループを終了する def deach(delayer=Delayer, &proc) to_enum.deach(delayer, &proc) end end delayer-deferred-1.0.3/lib/delayer/deferred/deferredable.rb0000644000175000017500000000552312615150722021704 0ustar daidai# -*- coding: utf-8 -*- require "delayer/deferred/version" # なんでもDeferred module Delayer::Deferred::Deferredable Callback = Struct.new(*%i) BackTrace = Struct.new(*%i) CallbackDefaultOK = lambda{ |x| x } CallbackDefaultNG = lambda{ |err| Delayer::Deferred.fail(err) } # このDeferredが成功した場合の処理を追加する。 # 新しいDeferredのインスタンスを返す def next(&proc) _post(:ok, &proc) end alias deferred next # このDeferredが失敗した場合の処理を追加する。 # 新しいDeferredのインスタンスを返す def trap(&proc) _post(:ng, &proc) end alias error trap # Deferredを直ちに実行する def call(value = nil) _call(:ok, value) end # Deferredを直ちに失敗させる def fail(exception = nil) _call(:ng, exception) end # この一連のDeferredをこれ以上実行しない def cancel @callback = Callback.new(CallbackDefaultOK, CallbackDefaultNG, BackTrace.new(nil, nil).freeze).freeze end def callback @callback ||= Callback.new(CallbackDefaultOK, CallbackDefaultNG, BackTrace.new(nil, nil)) end # second 秒待って次を実行する # ==== Args # [second] 待つ秒数(second) # ==== Return # Deferred def wait(second) self.next{ Thread.new{ sleep(second) } } end private def delayer self.class.delayer end def _call(stat = :ok, value = nil) begin catch(:__deferredable_success) do failed = catch(:__deferredable_fail) do n_value = _execute(stat, value) if n_value.is_a? Delayer::Deferred::Deferredable n_value.next{ |result| @next.call(result) }.trap{ |exception| @next.fail(exception) } else if defined?(@next) delayer.new{ @next.call(n_value) } else register_next_call(:ok, n_value) end end throw :__deferredable_success end _fail_action(failed) end rescue Exception => exception _fail_action(exception) end end def _execute(stat, value) callback[stat].call(value) end def _post(kind, &proc) @next = delayer.Deferred.new(self) @next.callback[kind] = proc @next.callback.backtrace[kind] = caller(1) if defined?(@next_call_stat) and defined?(@next_call_value) @next.__send__({ok: :call, ng: :fail}[@next_call_stat], @next_call_value) elsif defined?(@follow) and @follow.nil? call end @next end def register_next_call(stat, value) @next_call_stat, @next_call_value = stat, value self end def _fail_action(err_obj) if defined?(@next) delayer.new{ @next.fail(err_obj) } else register_next_call(:ng, err_obj) end end end delayer-deferred-1.0.3/lib/delayer/deferred/deferred.rb0000644000175000017500000000267112615150722021061 0ustar daidai# -*- coding: utf-8 -*- require "delayer/deferred/deferredable" require "delayer/deferred/tools" require "delayer/deferred/version" module Delayer::Deferred class Deferred extend Delayer::Deferred::Tools include Deferredable def self.inherited(subclass) subclass.extend(::Delayer::Deferred) end def self.Thread @thread_class ||= gen_thread_class end def self.gen_thread_class the_delayer = delayer Class.new(Thread) do define_singleton_method(:delayer) do the_delayer end end end def self.delayer ::Delayer end def self.new(*args) deferred = super(*args) if block_given? deferred.next(&Proc.new) else deferred end end def initialize(follow = nil) super() @follow = follow @backtrace = caller if ::Delayer::Deferred.debug end alias :deferredable_cancel :cancel def cancel deferredable_cancel @follow.cancel if @follow.is_a? Deferredable end def inspect if ::Delayer::Deferred.debug sprintf("#<%s: %p %s follow:%p stat:%s value:%s>".freeze, self.class, object_id, @backtrace.find{|n|not n.include?("delayer/deferred".freeze)}, @follow ? @follow.object_id : 0, @next_call_stat.inspect, @next_call_value.inspect) else sprintf("#<%s: %p stat:%s value:%s>".freeze, self.class, object_id, @next_call_stat.inspect, @next_call_value.inspect) end end end end delayer-deferred-1.0.3/lib/delayer/deferred.rb0000644000175000017500000000155312615150722017277 0ustar daidai# coding: utf-8 require "delayer" require "delayer/deferred/deferred" require "delayer/deferred/deferredable" require "delayer/deferred/enumerable" require "delayer/deferred/enumerator" require "delayer/deferred/thread" require "delayer/deferred/tools" require "delayer/deferred/version" module Delayer module Deferred extend Delayer::Deferred::Tools class << self #真ならデバッグ情報を集める attr_accessor :debug def new(*rest, &proc) Delayer::Deferred::Deferred.new(*rest, &proc) end end end module Extend def Deferred @deferred ||= begin the_delayer = self Class.new(::Delayer::Deferred::Deferred) { define_singleton_method(:delayer) { the_delayer } } end end end end Delayer::Deferred.debug = false delayer-deferred-1.0.3/delayer-deferred.gemspec0000644000175000017500000000176712615150722017556 0ustar daidai# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'delayer/deferred/version' Gem::Specification.new do |spec| spec.name = "delayer-deferred" spec.version = Delayer::Deferred::VERSION spec.authors = ["Toshiaki Asai"] spec.email = ["toshi.alternative@gmail.com"] spec.summary = %q{Deferred for Delayer} spec.description = %q{Deferred for Delayer.} spec.homepage = "" spec.license = "MIT" spec.files = `git ls-files -z`.split("\x0") spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] spec.required_ruby_version = '>= 2.0.0' spec.add_dependency "delayer", ">= 0.0.2", "< 0.1" spec.add_development_dependency "bundler", "~> 1.7" spec.add_development_dependency "rake", "~> 10.0" spec.add_development_dependency "minitest", "~> 5.7" end delayer-deferred-1.0.3/Rakefile0000644000175000017500000000024512615150722014441 0ustar daidairequire "bundler/gem_tasks" require "rake/testtask" Rake::TestTask.new do |t| t.test_files = FileList['test/*_test.rb'] t.warning = true t.verbose = true end delayer-deferred-1.0.3/README.md0000644000175000017500000000725312615150722014261 0ustar daidai# Delayer::Deferred Delayerを使って、jsdeferredをRubyに移植したものです。 jsdeferredでできること以外に、Thread、Enumeratorを拡張します。 ## Installation Add this line to your application's Gemfile: ```ruby gem 'delayer-deferred' ``` And then execute: $ bundle Or install it yourself as: $ gem install delayer-deferred ## Usage ### The first step rubygemでインストールしたあと、requireします。 ```ruby require "delayer/deferred" ``` `Delayer::Deferred.new` が使えるようになります。ブロックを渡すと、Delayerのように後から(Delayer.runが呼ばれた時に)実行されます。 ```ruby Delayer.default = Delayer.generate_class # Delayerの準備 Delayer::Deferred.new { p "defer" } Delayer.run ``` ``` defer ``` `.next` メソッドで、前のブロックの実行が終わったら、その結果を受け取って次を実行することができます。 ```ruby Delayer.default = Delayer.generate_class # Delayerの準備 Delayer::Deferred.new { 1 + 1 }.next{ |sum| p sum } Delayer.run ``` ``` 2 ``` ### Error handling nextブロックの中で例外が発生した場合、次のtrapブロックまで処理が飛ばされます。 trapブロックは、その例外オブジェクトを引数として受け取ります。 ```ruby Delayer.default = Delayer.generate_class # Delayerの準備 Delayer::Deferred.new { 1 / 0 }.next{ |sum| p sum }.trap{ |exception| puts "Error occured!" p exception } Delayer.run ``` ``` Error occured! \# ``` 例外が発生すると、以降のnextブロックは無視され、例外が起こったブロック以降の最初のtrapブロックが実行されます。trapブロックの後にnextブロックがあればそれが実行されます。 `Delayer::Deferred.fail()` を使えば、例外以外のオブジェクトをtrapの引数に渡すこともできます。 ```ruby Delayer.default = Delayer.generate_class # Delayerの準備 Delayer::Deferred.new { Delayer::Deferred.fail("test error message") }.trap{ |exception| puts "Error occured!" p exception } Delayer.run ``` ``` Error occured! "test error message" ``` ### Thread Threadには、Delayer::Deferred::Deferredableモジュールがincludeされていて、nextやtrapメソッドが使えます。 ```ruby Delayer.default = Delayer.generate_class # Delayerの準備 Thread.new { 1 + 1 }.next{ |sum| p sum } Delayer.run ``` ``` 2 ``` ### Automatically Divide a Long Loop `Enumerable#deach`, `Enumerator#deach`はeachの変種で、Delayerのexpireの値よりループに時間がかかったら一旦処理を中断して、続きを実行するDeferredを新たに作ります。 ```ruby complete = false Delayer.default = Delayer.generate_class(expire: 0.1) # Delayerの準備 (1..100000).deach{ |digit| p digit }.next{ puts "complete" complete = true }.trap{ |exception| p exception complete = true } while !complete Delayer.run puts "divided" end ``` ``` 1 2 3 (中略) 25398 divided 25399 (中略) 100000 complete divided ``` 開発している環境では、25398までループした後、0.1秒経過したので一度処理が分断され、Delayer.runから処理が帰ってきています。 また、このメソッドはDeferredを返すので、ループが終わった後に処理をしたり、エラーを受け取ったりできます。 ## Contributing 1. Fork it ( https://github.com/toshia/delayer-deferred/fork ) 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create a new Pull Request delayer-deferred-1.0.3/LICENSE.txt0000644000175000017500000000205612615150722014621 0ustar daidaiCopyright (c) 2015 Toshiaki Asai MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. delayer-deferred-1.0.3/Gemfile0000644000175000017500000000014512615150722014266 0ustar daidaisource 'https://rubygems.org' # Specify your gem's dependencies in delayer-deferred.gemspec gemspec delayer-deferred-1.0.3/.gitignore0000644000175000017500000000017612615150722014767 0ustar daidai/.bundle/ /.yardoc /Gemfile.lock /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ *.bundle *.so *.o *.a mkmf.log /vendor/