simple_stats_store 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.
- checksums.yaml +7 -0
- data/README.md +89 -0
- data/lib/simple_stats_store.rb +5 -0
- data/lib/simple_stats_store/file_dump.rb +40 -0
- data/lib/simple_stats_store/nil_dump.rb +7 -0
- data/lib/simple_stats_store/server.rb +37 -0
- metadata +48 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 03dc5993bc4a5e7ec010d5601add13295a9d3cfc
|
4
|
+
data.tar.gz: cfe61488fb2db2b0a2562515ee6efc2fcde61501
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4bb37b8ff0d17d9d5bac6258bc6af92a840ba68dda73e3f50d45a247a10d37e5b27e13d885910e3fe51379c3b51a00975113cdf07401ae8776ae90ba0063f382
|
7
|
+
data.tar.gz: fd35eec5a1d2904de47e6da818ab395b16b887b605506d05e4d27a10d48a7e9cb4868a007dbca4bc9c1427300446363b3a77308472c2cdae4c1d64354b9b1a32
|
data/README.md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# Simple Stats Store
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
The purpose of Simple Stats Store is to provide a simple and lightweight method
|
6
|
+
for multiple processes to dump data into an SQLite database without contention.
|
7
|
+
|
8
|
+
It is appropriate to be used when:
|
9
|
+
|
10
|
+
* There are multiple threads or processes submitting statistics
|
11
|
+
* Data concurrency is less important than avoiding waiting on database locks
|
12
|
+
|
13
|
+
This is achieved by the threads dropping uniquely named files into a common
|
14
|
+
directory containing the statistics which are then picked up by a single thread
|
15
|
+
that is the sole accessor of the database.
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
### General
|
20
|
+
|
21
|
+
Create the repository for temporary data files:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require 'simple_stats_store/file_dump'
|
25
|
+
|
26
|
+
dir = '/path/to/temporary/data/directory'
|
27
|
+
Dir.mkdir(dir)
|
28
|
+
data_dump = SimpleStatsStore::FileDump.new(dir)
|
29
|
+
```
|
30
|
+
|
31
|
+
### Server
|
32
|
+
|
33
|
+
Set up the database:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
require 'simple_stats_store/server'
|
37
|
+
|
38
|
+
db_file = '/path/to/database.sql'
|
39
|
+
ActiveRecord::Base.establish_connection(
|
40
|
+
adapter: :sqlite3,
|
41
|
+
database: db_file
|
42
|
+
)
|
43
|
+
ActiveRecord::Schema.define do
|
44
|
+
create_table :table do |table|
|
45
|
+
table.column :timestamp, :string
|
46
|
+
table.column :key_1, :integer
|
47
|
+
table.column :key_2, :float
|
48
|
+
# etc.
|
49
|
+
end
|
50
|
+
end
|
51
|
+
class Table < ActiveRecord::Base
|
52
|
+
end
|
53
|
+
|
54
|
+
ssss = SimpleStatsStore::Server.new(
|
55
|
+
data_dump: data_dump,
|
56
|
+
models: { table_ref: Table }
|
57
|
+
)
|
58
|
+
|
59
|
+
t_next = Time.new + 300
|
60
|
+
server_pid = ssss.run do
|
61
|
+
if Time.new >= t_next
|
62
|
+
# Code to be executed every 5 minutes
|
63
|
+
# ...
|
64
|
+
t_next += 300
|
65
|
+
end
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
### Client
|
70
|
+
|
71
|
+
Write data
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
data_dump.write(
|
75
|
+
table_ref,
|
76
|
+
{
|
77
|
+
timestamp: Time.new.to_s,
|
78
|
+
key_1: value_1,
|
79
|
+
key_2: value_2,
|
80
|
+
# etc.
|
81
|
+
}
|
82
|
+
)
|
83
|
+
```
|
84
|
+
|
85
|
+
## License
|
86
|
+
|
87
|
+
Simple Stats Store is available to everyone under the terms of the MIT open source licence. Take a look at the LICENSE file in the code.
|
88
|
+
|
89
|
+
Copyright (c) 2015 BBC
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module SimpleStatsStore
|
4
|
+
class FileDump
|
5
|
+
def initialize(dir)
|
6
|
+
@dir = dir
|
7
|
+
end
|
8
|
+
|
9
|
+
def files_contents
|
10
|
+
contents = []
|
11
|
+
Dir["#{@dir}/*"].each do |f|
|
12
|
+
data = File.open(f, 'r').read
|
13
|
+
if /\n---\n$/.match(data)
|
14
|
+
contents << data
|
15
|
+
File.delete(f)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
contents
|
19
|
+
end
|
20
|
+
|
21
|
+
def each(&block)
|
22
|
+
files_contents.each &block
|
23
|
+
end
|
24
|
+
|
25
|
+
def write(model, data)
|
26
|
+
i = 0
|
27
|
+
while File.exists?(File.expand_path("sss-#{$$}-#{Time.new.to_i}-#{i}.stats", @dir))
|
28
|
+
i += 1
|
29
|
+
end
|
30
|
+
File.open(File.expand_path("sss-#{$$}-#{Time.new.to_i}-#{i}.stats", @dir), 'w') do |f|
|
31
|
+
f.puts "---"
|
32
|
+
f.puts model
|
33
|
+
data.each do |key, value|
|
34
|
+
f.puts "#{key.to_s}: #{value}"
|
35
|
+
end
|
36
|
+
f.puts "---"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module SimpleStatsStore
|
2
|
+
class Server
|
3
|
+
def initialize(options)
|
4
|
+
@data_dump = options[:data_dump]
|
5
|
+
@models = options[:models]
|
6
|
+
end
|
7
|
+
|
8
|
+
def scan
|
9
|
+
@data_dump.each do |stats|
|
10
|
+
lines = stats.split("\n")
|
11
|
+
if lines.shift != '---' or lines.pop != '---'
|
12
|
+
puts "Corrupt statistics"
|
13
|
+
return false
|
14
|
+
end
|
15
|
+
|
16
|
+
model = lines.shift.strip
|
17
|
+
data = {}
|
18
|
+
lines.each do |l|
|
19
|
+
k, v = l.split(/:/, 2)
|
20
|
+
data[k.strip.to_sym] = v.strip
|
21
|
+
end
|
22
|
+
|
23
|
+
@models[model.to_sym].create(data)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def run(&block)
|
28
|
+
Process.fork do
|
29
|
+
loop do
|
30
|
+
self.scan
|
31
|
+
yield if block_given?
|
32
|
+
sleep 0.1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple_stats_store
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joe Haig
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-15 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Using SQLite3 to store statistics from a multithreaded application
|
14
|
+
email: joe.haig@bbc.co.uk
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- README.md
|
20
|
+
- lib/simple_stats_store.rb
|
21
|
+
- lib/simple_stats_store/file_dump.rb
|
22
|
+
- lib/simple_stats_store/nil_dump.rb
|
23
|
+
- lib/simple_stats_store/server.rb
|
24
|
+
homepage: https://github.com/bbc/simple_stats_store
|
25
|
+
licenses:
|
26
|
+
- MIT
|
27
|
+
metadata: {}
|
28
|
+
post_install_message:
|
29
|
+
rdoc_options: []
|
30
|
+
require_paths:
|
31
|
+
- lib
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '0'
|
37
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
requirements: []
|
43
|
+
rubyforge_project:
|
44
|
+
rubygems_version: 2.2.2
|
45
|
+
signing_key:
|
46
|
+
specification_version: 4
|
47
|
+
summary: Simple Stats Store
|
48
|
+
test_files: []
|