crampy 0.15.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,56 @@
1
+ module Cramp
2
+ module PeriodicTimer
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ # was class_inheritable_accessor
8
+ class_attribute :periodic_timers, :instance_reader => false
9
+ self.periodic_timers ||= []
10
+ end
11
+
12
+ module ClassMethods
13
+ def periodic_timer(method, options = {})
14
+ self.periodic_timers << [method, options]
15
+ end
16
+ end
17
+
18
+ def initialize(*)
19
+ super
20
+ @timers = []
21
+ end
22
+
23
+ protected
24
+
25
+ def continue
26
+ super
27
+ start_periodic_timers
28
+ end
29
+
30
+ def init_async_body
31
+ super
32
+
33
+ if self.class.periodic_timers.any?
34
+ @body.callback { stop_periodic_timers }
35
+ @body.errback { stop_periodic_timers }
36
+ end
37
+ end
38
+
39
+ def start_periodic_timers
40
+ self.class.periodic_timers.each do |method, options|
41
+ @timers << EventMachine::PeriodicTimer.new(options[:every] || 1) { timer_method_wrapper(method) unless @finished }
42
+ end
43
+ end
44
+
45
+ def stop_periodic_timers
46
+ @timers.each {|t| t.cancel }
47
+ end
48
+
49
+ def timer_method_wrapper(method)
50
+ send(method)
51
+ rescue StandardError, LoadError, SyntaxError => exception
52
+ handle_exception(exception)
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,11 @@
1
+ module Cramp
2
+ module Rendering
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ def render(body)
7
+ @body.call(body)
8
+ end
9
+
10
+ end
11
+ end
data/lib/cramp/sse.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Cramp
2
+ class SSE < Action
3
+ self.transport = :sse
4
+ end
5
+ end
@@ -0,0 +1,58 @@
1
+ require 'active_support'
2
+ require 'active_support/test_case'
3
+
4
+ module Cramp
5
+ class TestCase < ::ActiveSupport::TestCase
6
+
7
+ setup :create_request
8
+
9
+ def create_request
10
+ @request = Rack::MockRequest.new(app)
11
+ end
12
+
13
+ def get(path, options = {}, headers = {}, &block)
14
+ callback = options.delete(:callback) || block
15
+ headers = headers.merge('async.callback' => callback)
16
+
17
+ EM.run do
18
+ catch(:async) { @request.get(path, headers) }
19
+ end
20
+ end
21
+
22
+ def get_body(path, options = {}, headers = {}, &block)
23
+ callback = options.delete(:callback) || block
24
+ response_callback = proc {|response| response[-1].each {|chunk| callback.call(chunk) } }
25
+ headers = headers.merge('async.callback' => response_callback)
26
+
27
+ EM.run do
28
+ catch(:async) { @request.get(path, headers) }
29
+ end
30
+ end
31
+
32
+ def get_body_chunks(path, options = {}, headers = {}, &block)
33
+ callback = options.delete(:callback) || block
34
+ count = options.delete(:count) || 1
35
+
36
+ stopping = false
37
+ chunks = []
38
+
39
+ get_body(path, options, headers) do |body_chunk|
40
+ chunks << body_chunk unless stopping
41
+
42
+ if chunks.count >= count
43
+ stopping = true
44
+ callback.call(chunks) if callback
45
+ EM.next_tick { EM.stop }
46
+ end
47
+ end
48
+ end
49
+
50
+ def app
51
+ raise "Please define a method called 'app' returning an async Rack Application"
52
+ end
53
+
54
+ def stop
55
+ EM.stop
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ module Cramp
2
+ VERSION = '0.15.3'
3
+ end
@@ -0,0 +1,13 @@
1
+ module Cramp
2
+ class Websocket < Action
3
+ self.transport = :websocket
4
+
5
+ class << self
6
+ def backend=(backend)
7
+ raise "Websocket backend #{backend} is unknown" unless [:thin, :rainbows].include?(backend.to_sym)
8
+ Faye::WebSocket.load_adapter(backend.to_s)
9
+ end
10
+ end
11
+
12
+ end
13
+ end
data/lib/cramp.rb ADDED
@@ -0,0 +1,47 @@
1
+ require 'eventmachine'
2
+ # this shoud be called before reactor start, otherwise EM will silently ignore it
3
+ EM.epoll
4
+
5
+ require 'active_support'
6
+ require 'active_support/core_ext/class/attribute'
7
+ #require 'active_support/core_ext/class/inheritable_attributes'
8
+ require 'active_support/core_ext/class/attribute_accessors'
9
+ require 'active_support/core_ext/module/aliasing'
10
+ require 'active_support/core_ext/module/attribute_accessors'
11
+ require 'active_support/core_ext/kernel/reporting'
12
+ require 'active_support/concern'
13
+ require 'active_support/core_ext/hash/indifferent_access'
14
+ require 'active_support/core_ext/hash/except'
15
+ require 'active_support/buffered_logger'
16
+
17
+ require 'rack'
18
+ require 'faye/websocket'
19
+
20
+ begin
21
+ require 'fiber'
22
+ require File.join(File.dirname(__FILE__), 'vendor/fiber_pool')
23
+ rescue LoadError
24
+ # No fibers available!
25
+ end
26
+
27
+ module Cramp
28
+ ROOT = File.expand_path(File.dirname(__FILE__))
29
+ require "#{Cramp::ROOT}/cramp/version"
30
+
31
+ mattr_accessor :logger
32
+
33
+ autoload :Action, "cramp/action"
34
+ autoload :Websocket, "cramp/websocket"
35
+ autoload :WebsocketExtension, "cramp/websocket/extension"
36
+ autoload :Protocol10FrameParser, "cramp/websocket/protocol10_frame_parser"
37
+ autoload :SSE, "cramp/sse"
38
+ autoload :LongPolling, "cramp/long_polling"
39
+ autoload :Body, "cramp/body"
40
+ autoload :PeriodicTimer, "cramp/periodic_timer"
41
+ autoload :KeepConnectionAlive, "cramp/keep_connection_alive"
42
+ autoload :Abstract, "cramp/abstract"
43
+ autoload :Callbacks, "cramp/callbacks"
44
+ autoload :FiberPool, "cramp/fiber_pool"
45
+ autoload :ExceptionHandler, "cramp/exception_handler"
46
+ autoload :TestCase, "cramp/test_case"
47
+ end
data/lib/crampy.rb ADDED
@@ -0,0 +1,4 @@
1
+ require File.expand_path('../cramp', __FILE__)
2
+
3
+ # no namespace change yet
4
+ Crampy = Cramp
@@ -0,0 +1,85 @@
1
+ # Author:: Mohammad A. Ali (mailto:oldmoe@gmail.com)
2
+ # Copyright:: Copyright (c) 2008 eSpace, Inc.
3
+ # License:: Distributes under the same terms as Ruby
4
+
5
+ require 'fiber'
6
+
7
+ class Fiber
8
+
9
+ #Attribute Reference--Returns the value of a fiber-local variable, using
10
+ #either a symbol or a string name. If the specified variable does not exist,
11
+ #returns nil.
12
+ def [](key)
13
+ local_fiber_variables[key]
14
+ end
15
+
16
+ #Attribute Assignment--Sets or creates the value of a fiber-local variable,
17
+ #using either a symbol or a string. See also Fiber#[].
18
+ def []=(key,value)
19
+ local_fiber_variables[key] = value
20
+ end
21
+
22
+ private
23
+
24
+ def local_fiber_variables
25
+ @local_fiber_variables ||= {}
26
+ end
27
+ end
28
+
29
+ class FiberPool
30
+
31
+ # gives access to the currently free fibers
32
+ attr_reader :fibers
33
+ attr_reader :busy_fibers
34
+
35
+ # Code can register a proc with this FiberPool to be called
36
+ # every time a Fiber is finished. Good for releasing resources
37
+ # like ActiveRecord database connections.
38
+ attr_accessor :generic_callbacks
39
+
40
+ # Prepare a list of fibers that are able to run different blocks of code
41
+ # every time. Once a fiber is done with its block, it attempts to fetch
42
+ # another one from the queue
43
+ def initialize(count = 100)
44
+ @fibers,@busy_fibers,@queue,@generic_callbacks = [],{},[],[]
45
+ count.times do |i|
46
+ fiber = Fiber.new do |block|
47
+ loop do
48
+ block.call
49
+
50
+ # callbacks are called in a reverse order, much like c++ destructor
51
+ Fiber.current[:callbacks].pop.call while Fiber.current[:callbacks].length > 0
52
+ generic_callbacks.each do |cb|
53
+ cb.call
54
+ end
55
+
56
+ if @queue.any?
57
+ block = @queue.shift
58
+ else
59
+ @busy_fibers.delete(Fiber.current.object_id)
60
+ @fibers.unshift Fiber.current
61
+ block = Fiber.yield
62
+ end
63
+
64
+ end
65
+ end
66
+ fiber[:callbacks] = []
67
+ fiber[:em_keys] = []
68
+ @fibers << fiber
69
+ end
70
+ end
71
+
72
+ # If there is an available fiber use it, otherwise, leave it to linger
73
+ # in a queue
74
+ def spawn(&block)
75
+ if fiber = @fibers.shift
76
+ fiber[:callbacks] = []
77
+ @busy_fibers[fiber.object_id] = fiber
78
+ fiber.resume(block)
79
+ else
80
+ @queue << block
81
+ end
82
+ self # we are keen on hiding our queue
83
+ end
84
+
85
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: crampy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.15.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Pratik Naik
9
+ - Vasily Fedoseyev
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-06-12 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ requirement: &70186850572180 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '3.2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *70186850572180
26
+ - !ruby/object:Gem::Dependency
27
+ name: rack
28
+ requirement: &70186850570900 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *70186850570900
37
+ - !ruby/object:Gem::Dependency
38
+ name: eventmachine
39
+ requirement: &70186850569540 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: 1.0.0.beta.3
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: *70186850569540
48
+ - !ruby/object:Gem::Dependency
49
+ name: faye-websocket
50
+ requirement: &70186850567380 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: '0.3'
56
+ type: :runtime
57
+ prerelease: false
58
+ version_requirements: *70186850567380
59
+ - !ruby/object:Gem::Dependency
60
+ name: thor
61
+ requirement: &70186850565720 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ~>
65
+ - !ruby/object:Gem::Version
66
+ version: '0.14'
67
+ type: :runtime
68
+ prerelease: false
69
+ version_requirements: *70186850565720
70
+ description: Crampy is a fork of Cramp, a framework for developing asynchronous web
71
+ applications.
72
+ email:
73
+ - vasilyfedoseyev@gmail.com
74
+ executables:
75
+ - cramp
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - MIT-LICENSE
80
+ - lib/cramp/abstract.rb
81
+ - lib/cramp/action.rb
82
+ - lib/cramp/body.rb
83
+ - lib/cramp/callbacks.rb
84
+ - lib/cramp/exception_handler.rb
85
+ - lib/cramp/fiber_pool.rb
86
+ - lib/cramp/generators/application.rb
87
+ - lib/cramp/generators/templates/application/app/actions/home_action.rb
88
+ - lib/cramp/generators/templates/application/application.rb
89
+ - lib/cramp/generators/templates/application/config/database.yml
90
+ - lib/cramp/generators/templates/application/config/routes.rb
91
+ - lib/cramp/generators/templates/application/config.ru
92
+ - lib/cramp/generators/templates/application/Gemfile
93
+ - lib/cramp/keep_connection_alive.rb
94
+ - lib/cramp/long_polling.rb
95
+ - lib/cramp/periodic_timer.rb
96
+ - lib/cramp/rendering.rb
97
+ - lib/cramp/sse.rb
98
+ - lib/cramp/test_case.rb
99
+ - lib/cramp/version.rb
100
+ - lib/cramp/websocket.rb
101
+ - lib/cramp.rb
102
+ - lib/crampy.rb
103
+ - lib/vendor/fiber_pool.rb
104
+ - bin/cramp
105
+ homepage: https://github.com/Vasfed/cramp
106
+ licenses: []
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ! '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 1.8.15
126
+ signing_key:
127
+ specification_version: 3
128
+ summary: Asynchronous web framework.
129
+ test_files: []
130
+ has_rdoc: false