liquid-ext 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ module FromFile
4
+
5
+ module ClassMethods
6
+ def from_file(path)
7
+ new.tap do |obj|
8
+ obj.from_file(path)
9
+ end
10
+ end
11
+ end
12
+
13
+ def from_file(path)
14
+ if File.exists?(path) && File.readable?(path)
15
+ self.instance_eval(IO.read(path), path, 1)
16
+ else
17
+ raise IOError, "Cannot open or read #{path}!"
18
+ end
19
+ end
20
+
21
+ def self.included(receiver)
22
+ receiver.extend(ClassMethods)
23
+ end
24
+
25
+ end
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+ require 'metriks'
3
+ require 'singleton'
4
+
5
+ class GCStats
6
+ include Singleton
7
+
8
+ # RUBY 1.9.X-Implementation
9
+ module Yarv
10
+ def enable
11
+ GC::Profiler.enable
12
+ end
13
+
14
+ def clear
15
+ GC::Profiler.clear
16
+ end
17
+
18
+ def gather
19
+ count_collections
20
+ count_allocations
21
+ count_objects
22
+ Metriks.timer('gc_stats.total_time').update(GC::Profiler.total_time)
23
+ end
24
+
25
+ def count_collections
26
+ Metriks.histogram('gc_stats.collections').update(GC.count)
27
+ end
28
+
29
+ def count_allocations
30
+ allocated_size = GC.respond_to?(:malloc_allocated_size) ? GC.malloc_allocated_size / 1000.0 : 0
31
+ Metriks.histogram('gc_stats.allocated').update(allocated_size)
32
+ end
33
+
34
+ def count_objects
35
+ objects = ObjectSpace.count_objects
36
+ objects = objects[:TOTAL] - objects[:FREE]
37
+ Metriks.histogram('gc_stats.objects').update(objects)
38
+ end
39
+ end
40
+
41
+ if RUBY_ENGINE == 'ruby' and RUBY_VERSION =~ /^1\.9/
42
+ extend Yarv
43
+ end
44
+
45
+ def self.available?
46
+ respond_to?(:gather)
47
+ end
48
+
49
+ def self.start!
50
+ if available?
51
+ enable
52
+ $log.info("gc:stats", enabled: true)
53
+
54
+ EventMachine.next_tick do
55
+ EventMachine::PeriodicTimer.new(60*60) do
56
+ GC.start
57
+ end
58
+
59
+ EventMachine::PeriodicTimer.new(60) do
60
+ gather
61
+ clear
62
+ end
63
+ end
64
+ else
65
+ $log.info("gc:stats", enabled: false)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ require 'digest'
4
+
5
+ class HashHelper
6
+ def self.numeric_hash(val)
7
+ # Use a the first 15 bytes of a MD5 bytes - small enough to be represented as Fixnum => no garbage collection
8
+ Digest::MD5.hexdigest(val.to_s)[0..14].to_i(16)
9
+ end
10
+ end
@@ -0,0 +1,56 @@
1
+ require 'liquid/sysconf'
2
+
3
+ ProcStat = Struct.new(
4
+ :ppid,
5
+ :pgrp,
6
+ :session,
7
+ :tty_nr,
8
+ :tpgid,
9
+ :flags,
10
+ :minflt,
11
+ :cminflt,
12
+ :majflt,
13
+ :cmajflt,
14
+ :utime,
15
+ :stime,
16
+ :cutime,
17
+ :cstime,
18
+ :priority,
19
+ :nice,
20
+ :num_threads,
21
+ :itrealvalue,
22
+ :starttime,
23
+ :vsize,
24
+ :rss,
25
+ :rsslim,
26
+ :startcode,
27
+ :endcode,
28
+ :startstack,
29
+ :kstkesp,
30
+ :kstkeip,
31
+ :signal,
32
+ :blocked,
33
+ :sigignore,
34
+ :sigcatch,
35
+ :wchan,
36
+ :nswap,
37
+ :cnswap,
38
+ :exit_signal,
39
+ :processor,
40
+ :rt_priority,
41
+ :policy,
42
+ :delayacct_blkio_ticks,
43
+ :guest_time,
44
+ :cguest_time
45
+ )
46
+
47
+ class ProcStat
48
+ def self.read
49
+ stat = File.read("/proc/self/stat").chomp.split
50
+ new(*stat[3..40].map(&:to_i))
51
+ end
52
+
53
+ def pagesize
54
+ Sysconf.sysconf(:page_size)
55
+ end
56
+ end
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ require 'liquid/from_file'
4
+
5
+ class Router
6
+ include FromFile
7
+
8
+ attr_accessor :routes
9
+
10
+ def initialize(request_handler)
11
+ @request_handler = request_handler
12
+ @routes = []
13
+
14
+ @cache = Hash.new do |hash, path|
15
+ hash[path] = nil
16
+ @routes.each do |regex, block, args|
17
+ match = path.match(regex)
18
+ hash[path] = block.curry[match] if match
19
+ end
20
+ hash[path]
21
+ end
22
+ end
23
+
24
+ def add(regexp, args, &block)
25
+ @routes << [regexp, block, args]
26
+ end
27
+
28
+ # route %r(/foo/(.+)/(\w+)/(\d+)), AnyParser, :matches, :in, :order
29
+ def route(regexp, parser, *args, &block)
30
+ block = lambda do |match, env|
31
+ params = args.each_with_index.inject({}) do |hash, (name, index)|
32
+ hash[name] = match[index+1]
33
+ hash
34
+ end
35
+
36
+ return @request_handler.handle(parser, env, params)
37
+ end
38
+
39
+ add(regexp, args, &block)
40
+ end
41
+
42
+ def handle(path, request)
43
+ @cache[path].call(request) if @cache[path]
44
+ return !! @cache[path]
45
+ end
46
+ end
@@ -0,0 +1,11 @@
1
+ require 'singleton'
2
+ require 'metriks'
3
+ require 'metriks/reporter/logger'
4
+
5
+ class Statistics
6
+ include Singleton
7
+
8
+ def initialize
9
+ Metriks::Reporter::Logger.new(:logger => $log, :interval => 300).start
10
+ end
11
+ end
@@ -0,0 +1,25 @@
1
+ require 'ffi'
2
+ require 'ffi/tools/const_generator'
3
+
4
+ module Sysconf
5
+ extend FFI::Library
6
+ ffi_lib ["c"]
7
+
8
+ fcg = FFI::ConstGenerator.new do |gen|
9
+ gen.include 'unistd.h'
10
+
11
+ %w[
12
+ _SC_PAGE_SIZE
13
+ _SC_VERSION
14
+ ].each do |const|
15
+ ruby_name = const.sub(/^_SC_/, '').downcase.to_sym
16
+ gen.const(const, "%d", nil, ruby_name, &:to_i)
17
+ end
18
+ end
19
+
20
+ CONF = enum(*fcg.constants.map{|_, const|
21
+ [const.ruby_name, const.converted_value]
22
+ }.flatten)
23
+
24
+ attach_function :sysconf, [CONF], :long
25
+ end
@@ -0,0 +1,6 @@
1
+ desc "build all protocol buffer schemas"
2
+ task :protoc do
3
+ Dir["**/*.proto"].each do |file|
4
+ sh "ruby-protoc #{file}"
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ begin
2
+ require 'reek/rake/task'
3
+ Reek::Rake::Task.new do |t|
4
+ t.fail_on_error = false
5
+ end
6
+ rescue LoadError
7
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ require 'liquid/router'
4
+ require 'terminal-table'
5
+
6
+ desc "Show all ed routes"
7
+ task :routes do
8
+ root = File.expand_path(File.dirname(__FILE__))
9
+ router = Router.new(lambda{})
10
+ router.from_file(File.join(root, "../../../config/routes.rb"))
11
+ routes = router.routes.map {|r| [r[0].inspect, r[1], r[2] ] }
12
+ puts Terminal::Table.new({
13
+ rows: routes.sort_by { |route| route[0] },
14
+ headings: ['regex', 'handler', 'parameters'],
15
+ })
16
+ end
17
+
@@ -0,0 +1,17 @@
1
+ begin
2
+ require 'rspec'
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc "Run the specs"
6
+ RSpec::Core::RakeTask.new do |t|
7
+ t.verbose = false
8
+ t.rspec_opts = [
9
+ '--require', 'spec_helper',
10
+ '--color',
11
+ '--format', 'Fuubar'
12
+ ]
13
+ end
14
+
15
+ task :default => [:spec]
16
+ rescue LoadError
17
+ end
@@ -0,0 +1,8 @@
1
+ begin
2
+ require 'yard'
3
+
4
+ YARD::Rake::YardocTask.new do |t|
5
+ t.files = ['lib/**/*.rb', 'README.rdoc']
6
+ end
7
+ rescue LoadError
8
+ end
@@ -0,0 +1 @@
1
+ Dir[File.expand_path('../tasks/*.rake', __FILE__)].each { |t| load t }
@@ -0,0 +1,13 @@
1
+ class TransactionId
2
+
3
+ @@current = nil
4
+
5
+ def self.current
6
+ @@current
7
+ end
8
+
9
+ def self.next
10
+ @@current = "#{Time.now.to_i}-#{Process.pid}-#{rand(89999) + 10000}"
11
+ end
12
+
13
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "liquid-ext"
5
+ spec.version = "1.0.0"
6
+ spec.authors = ["LiquidM, Inc."]
7
+ spec.email = ["opensource@liquidm.com"]
8
+ spec.description = %q{Ruby core extensions and helper libraries}
9
+ spec.summary = %q{Ruby core extensions and helper libraries}
10
+ spec.homepage = "https://github.com/liquidm/ext"
11
+
12
+ spec.files = `git ls-files`.split($/)
13
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
14
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
15
+ spec.require_paths = ["lib"]
16
+
17
+ spec.add_dependency "activesupport"
18
+ spec.add_dependency "ffi"
19
+ spec.add_dependency "liquid-logging", ">= 2.0.0"
20
+ spec.add_dependency "metriks"
21
+ spec.add_dependency "mixlib-cli"
22
+ spec.add_dependency "terminal-table"
23
+ end
@@ -0,0 +1,25 @@
1
+ require 'liquid/ext/enumerable'
2
+
3
+ describe Enumerable do
4
+
5
+ it "should support the sum for a list of numbers" do
6
+ [1,2,3,4,5].sum.should == 15
7
+ end
8
+
9
+ it "should support the mean for a list of numbers" do
10
+ [1,2,3,4,5].mean.should == 3.0
11
+ end
12
+
13
+ it "should support the variance for a list of numbers" do
14
+ [9,8,7,6,5].variance.should == 2.5
15
+ end
16
+
17
+ it "should support the standard deviation for a list of numbers" do
18
+ [9,8,7,6,5].stdev.should == 1.5811388300841898
19
+ end
20
+
21
+ it "should support a percentile method for a list of numbers" do
22
+ [9,1,8,2,7,3,6,4,5,4,3,2,1].percentile(0.9).should == 8
23
+ end
24
+
25
+ end
@@ -0,0 +1,77 @@
1
+ # encoding: utf-8
2
+
3
+ require 'liquid/router'
4
+
5
+ class GeneralRequestHandler; end
6
+
7
+ describe Router do
8
+ let(:regex) { %r(foo(.*)bar) }
9
+ let(:block) { Proc.new { 1+1 } }
10
+ let(:router) { Router.new(GeneralRequestHandler) }
11
+
12
+ describe '.add' do
13
+ context 'add route' do
14
+
15
+ before { router.add(regex, [:args], &block) }
16
+
17
+ context 'regex' do
18
+ subject { router.routes.last[0] }
19
+ it { should eql regex }
20
+ end
21
+
22
+ context 'block' do
23
+ subject { router.routes.last[1] }
24
+ its(:call) { should eql block.call }
25
+ end
26
+
27
+ context 'args' do
28
+ subject { router.routes.last[2] }
29
+ it { should eql [:args] }
30
+ end
31
+ end
32
+ end
33
+
34
+ describe '.route' do
35
+ let(:regex) { %r(/bar/) }
36
+
37
+ let(:parser) { double('CustomRequestParser') }
38
+ let(:env) { "env" }
39
+
40
+ before { router.route(regex, parser, :foo, :bar) }
41
+
42
+ subject { router.routes.last[0] }
43
+
44
+ it { should be_a Regexp }
45
+ it { should eql regex }
46
+ it 'builds correct block' do
47
+ GeneralRequestHandler.should_receive(:handle).with(parser, env, {foo: 1, bar: 2})
48
+
49
+ _, block = router.routes.last
50
+ block.call([0,1,2], env)
51
+ end
52
+ end
53
+
54
+ describe '.handle' do
55
+ let(:handler) { double('MockHandler') }
56
+ let(:request) { double('request') }
57
+ let(:url_re_1) { 'http://ad.madvertise.de/uchte/(.*?)' }
58
+ let(:url_re_2) { 'http://ad.madvertise.de/muchte/(.*?)' }
59
+ let(:block) { Proc.new {|match, env| handler.handle(match, env) } }
60
+
61
+ before do
62
+ router.add url_re_1, [:foo] { }
63
+ router.add url_re_2, [:bar], &block
64
+ router.route %r(/new_adx_bidrequest/([\w.-]+)), GeneralRequestHandler, :site_token
65
+ end
66
+
67
+ it 'is not matching' do
68
+ router.handle("http://ad.madvertise.de/muchtel", request).should == false
69
+ end
70
+
71
+ it 'is matching' do
72
+ handler.should_receive(:handle)
73
+ router.handle("http://ad.madvertise.de/muchte/foo", request).should == true
74
+ end
75
+ end
76
+ end
77
+
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+
4
+ require 'simplecov'
5
+ SimpleCov.start
6
+
7
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
8
+
9
+ RSpec.configure do |config|
10
+ end
metadata ADDED
@@ -0,0 +1,170 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: liquid-ext
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - LiquidM, Inc.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ requirement: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - '>='
23
+ - !ruby/object:Gem::Version
24
+ version: '0'
25
+ prerelease: false
26
+ type: :runtime
27
+ - !ruby/object:Gem::Dependency
28
+ name: ffi
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ prerelease: false
40
+ type: :runtime
41
+ - !ruby/object:Gem::Dependency
42
+ name: liquid-logging
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: 2.0.0
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - '>='
51
+ - !ruby/object:Gem::Version
52
+ version: 2.0.0
53
+ prerelease: false
54
+ type: :runtime
55
+ - !ruby/object:Gem::Dependency
56
+ name: metriks
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ prerelease: false
68
+ type: :runtime
69
+ - !ruby/object:Gem::Dependency
70
+ name: mixlib-cli
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ prerelease: false
82
+ type: :runtime
83
+ - !ruby/object:Gem::Dependency
84
+ name: terminal-table
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirement: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ prerelease: false
96
+ type: :runtime
97
+ description: Ruby core extensions and helper libraries
98
+ email:
99
+ - opensource@liquidm.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - .gitignore
105
+ - .travis.yml
106
+ - .yardopts
107
+ - Gemfile
108
+ - LICENSE
109
+ - README.md
110
+ - Rakefile
111
+ - lib/liquid/benchmark.rb
112
+ - lib/liquid/boot.rb
113
+ - lib/liquid/cli.rb
114
+ - lib/liquid/configuration.rb
115
+ - lib/liquid/environment.rb
116
+ - lib/liquid/ext/array.rb
117
+ - lib/liquid/ext/enumerable.rb
118
+ - lib/liquid/ext/hash.rb
119
+ - lib/liquid/ext/nil.rb
120
+ - lib/liquid/ext/object_space.rb
121
+ - lib/liquid/ext/ordered_set.rb
122
+ - lib/liquid/ext/signal.rb
123
+ - lib/liquid/ext/string.rb
124
+ - lib/liquid/ext/thread.rb
125
+ - lib/liquid/from_file.rb
126
+ - lib/liquid/gc_stats.rb
127
+ - lib/liquid/hash_helper.rb
128
+ - lib/liquid/proc_stat.rb
129
+ - lib/liquid/router.rb
130
+ - lib/liquid/statistics.rb
131
+ - lib/liquid/sysconf.rb
132
+ - lib/liquid/tasks.rb
133
+ - lib/liquid/tasks/protoc.rake
134
+ - lib/liquid/tasks/reek.rake
135
+ - lib/liquid/tasks/router.rake
136
+ - lib/liquid/tasks/rspec.rake
137
+ - lib/liquid/tasks/yard.rake
138
+ - lib/liquid/transaction_id.rb
139
+ - liquid-ext.gemspec
140
+ - spec/lib/liquid/ext/enumerable_spec.rb
141
+ - spec/lib/liquid/router_spec.rb
142
+ - spec/spec_helper.rb
143
+ homepage: https://github.com/liquidm/ext
144
+ licenses: []
145
+ metadata: {}
146
+ post_install_message:
147
+ rdoc_options: []
148
+ require_paths:
149
+ - lib
150
+ required_ruby_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - '>='
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ required_rubygems_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ requirements: []
161
+ rubyforge_project:
162
+ rubygems_version: 2.1.9
163
+ signing_key:
164
+ specification_version: 4
165
+ summary: Ruby core extensions and helper libraries
166
+ test_files:
167
+ - spec/lib/liquid/ext/enumerable_spec.rb
168
+ - spec/lib/liquid/router_spec.rb
169
+ - spec/spec_helper.rb
170
+ has_rdoc: