liquid-ext 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: