objectstore 1.1.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/atech/object_store.rb +10 -8
- data/lib/atech/object_store/connection.rb +43 -0
- data/lib/atech/object_store/file.rb +18 -15
- data/lib/atech/object_store/version.rb +5 -0
- metadata +20 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 66e598ae7b0fe9b6c113a6eddb9b537a932546eb
|
4
|
+
data.tar.gz: 651558ef45223a9f6882e4c3090813b6819b25ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1901b6334397f8796f6bdbb2d7bcb1fbb3ae5c75eb7d119f3fc8c1e1445c93f80348bc6abb7f18e371870969ac818569501dbe96f11a0840c94ec971d831cbc
|
7
|
+
data.tar.gz: 2fc2609f51c372a1e9a68b7ab75f6b3be15a87aaded85f609fe376e42e3800afdfee735c61b83489ccf06da5e94fe9e01ef3f53f872e80d0adcea7f55e4348a2
|
data/lib/atech/object_store.rb
CHANGED
@@ -1,21 +1,23 @@
|
|
1
1
|
module Atech
|
2
|
+
# Global module, contains configuration information
|
2
3
|
module ObjectStore
|
3
|
-
VERSION = '1.1.2'
|
4
|
-
|
5
4
|
## Error class which all Object Store errors are inherited fro
|
6
5
|
class Error < StandardError; end
|
7
|
-
|
6
|
+
|
8
7
|
class << self
|
9
|
-
|
8
|
+
# Hash to be passed to Mysql2::Client when creating a new client
|
9
|
+
attr_accessor :backend_options
|
10
|
+
|
11
|
+
# Largest file that can be uploaded to the database
|
10
12
|
attr_accessor :maximum_file_size
|
11
|
-
|
13
|
+
|
12
14
|
def maximum_file_size
|
13
|
-
@maximum_file_size ||= 1024 * 1024 * 1024
|
15
|
+
@maximum_file_size ||= 1024 * 1024 * 1024 # 1.megabyte
|
14
16
|
end
|
15
|
-
|
16
17
|
end
|
17
|
-
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
require 'atech/object_store/connection'
|
21
22
|
require 'atech/object_store/file'
|
23
|
+
require 'atech/object_store/version'
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Atech
|
2
|
+
module ObjectStore
|
3
|
+
# A very simple connection pool. Allows as many connections as MySQL is happy to give us. Probably not
|
4
|
+
# compatible with a truly concurrent Ruby due to the use of Array#shift, but good enough for MRI
|
5
|
+
module Connection
|
6
|
+
@free_clients = []
|
7
|
+
|
8
|
+
# Get an available connection (or create a new one) and yield it to the passed block. Places the client into
|
9
|
+
# @free_clients once done.
|
10
|
+
#
|
11
|
+
# @yield [client] Block that wishes to access database
|
12
|
+
# @yieldparam [Mysql2::Client] client A mysql2 client just for this block
|
13
|
+
#
|
14
|
+
# @return [Object] Result of the block
|
15
|
+
def self.client
|
16
|
+
client = @free_clients.shift || new_client
|
17
|
+
return_value = nil
|
18
|
+
tries = 2
|
19
|
+
begin
|
20
|
+
return_value = yield client
|
21
|
+
rescue Mysql2::Error => e
|
22
|
+
if e.message =~ /(lost connection|gone away)/i && (tries -= 1) > 0
|
23
|
+
retry
|
24
|
+
else
|
25
|
+
raise
|
26
|
+
end
|
27
|
+
ensure
|
28
|
+
@free_clients << client
|
29
|
+
end
|
30
|
+
return_value
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# Build a new Mysql2 client with the options suppplied in backend_options
|
36
|
+
#
|
37
|
+
# @return [Mysql2::Client] Fresh mysql2 client
|
38
|
+
def self.new_client
|
39
|
+
Mysql2::Client.new(Atech::ObjectStore.backend_options)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module Atech
|
2
2
|
module ObjectStore
|
3
3
|
class File
|
4
|
-
|
5
4
|
## Raised when a file cannot be found
|
6
5
|
class FileNotFound < Error; end
|
7
6
|
|
@@ -14,10 +13,14 @@ module Atech
|
|
14
13
|
## Raised if the data is larger than the maximum file size
|
15
14
|
class FileDataTooBig < Error; end
|
16
15
|
|
17
|
-
|
16
|
+
# Run a single query on a backend connection. This should only be used when running a single query. If you need
|
17
|
+
# to do multiple things on the same connection (e.g. INSERT and then get LAST_INSERT_ID) you should checkot your
|
18
|
+
# own connection using ObejctStore::Connection.client
|
18
19
|
def self.execute_query(query)
|
19
20
|
tries ||= 3
|
20
|
-
ObjectStore.
|
21
|
+
ObjectStore::Connection.client do |client|
|
22
|
+
client.query(query)
|
23
|
+
end
|
21
24
|
rescue Mysql2::Error => e
|
22
25
|
retry unless (tries -= 1).zero?
|
23
26
|
raise
|
@@ -52,32 +55,34 @@ module Atech
|
|
52
55
|
## Inserts a new File into the database. Returns a new object if successfully inserted or raises an error.
|
53
56
|
## Filename & data must be provided, options options will be added automatically unless specified.
|
54
57
|
def self.add_file(filename, data = '', options = {})
|
55
|
-
|
56
58
|
if data.bytesize > Atech::ObjectStore.maximum_file_size
|
57
59
|
raise FileDataTooBig, "Data provided was #{data.bytesize} and the maximum size is #{Atech::ObjectStore.maximum_file_size}"
|
58
60
|
end
|
59
61
|
|
60
|
-
|
62
|
+
# Create a hash of properties to be for this class
|
61
63
|
options[:name] = filename
|
62
64
|
options[:size] ||= data.bytesize
|
63
65
|
options[:blob] = data
|
64
66
|
options[:created_at] ||= Time.now
|
65
67
|
options[:updated_at] ||= Time.now
|
66
68
|
|
67
|
-
|
69
|
+
# Ensure that new files have a filename & data
|
68
70
|
raise ValidationError, "A 'name' must be provided to add a new file" if options[:name].nil?
|
69
71
|
|
70
|
-
|
72
|
+
# Encode timestamps
|
71
73
|
options[:created_at] = options[:created_at].utc
|
72
74
|
options[:updated_at] = options[:updated_at].utc
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
76
|
+
# Create an insert query
|
77
|
+
last_insert_id = ObjectStore::Connection.client do |client|
|
78
|
+
columns = options.keys.join('`,`')
|
79
|
+
data = options.values.map { |v| escape_and_quote(v) }.join(',')
|
80
|
+
client.query("INSERT INTO files (`#{columns}`) VALUES (#{data})")
|
81
|
+
client.last_id
|
82
|
+
end
|
78
83
|
|
79
84
|
## Return a new File object
|
80
|
-
self.new(options.merge(
|
85
|
+
self.new(options.merge(:id => last_insert_id))
|
81
86
|
end
|
82
87
|
|
83
88
|
## Initialises a new File object with the hash of attributes from a MySQL query ensuring that
|
@@ -179,14 +184,12 @@ module Atech
|
|
179
184
|
|
180
185
|
def self.escape_and_quote(string)
|
181
186
|
string = string.strftime('%Y-%m-%d %H:%M:%S') if string.is_a?(Time)
|
182
|
-
"'#{
|
187
|
+
"'#{Mysql2::Client.escape(string.to_s)}'"
|
183
188
|
end
|
184
189
|
|
185
190
|
def self.time_now
|
186
191
|
Time.now.utc.strftime('%Y-%m-%d %H:%M:%S')
|
187
192
|
end
|
188
|
-
|
189
|
-
|
190
193
|
end
|
191
194
|
end
|
192
195
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: objectstore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Cooke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
11
|
+
date: 2017-03-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: mysql2
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.3'
|
13
27
|
description:
|
14
28
|
email: adam@atechmedia.com
|
15
29
|
executables: []
|
@@ -17,7 +31,9 @@ extensions: []
|
|
17
31
|
extra_rdoc_files: []
|
18
32
|
files:
|
19
33
|
- lib/atech/object_store.rb
|
34
|
+
- lib/atech/object_store/connection.rb
|
20
35
|
- lib/atech/object_store/file.rb
|
36
|
+
- lib/atech/object_store/version.rb
|
21
37
|
- schema.sql
|
22
38
|
homepage: http://www.atechmedia.com
|
23
39
|
licenses: []
|
@@ -38,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
38
54
|
version: '0'
|
39
55
|
requirements: []
|
40
56
|
rubyforge_project:
|
41
|
-
rubygems_version: 2.
|
57
|
+
rubygems_version: 2.5.1
|
42
58
|
signing_key:
|
43
59
|
specification_version: 4
|
44
60
|
summary: A SQL based object store library
|