sdb_dal 0.0.1

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,366 @@
1
+ module SdbDal
2
+ $KCODE = 'u'
3
+ require "aws_sdb"
4
+ require "sdb_dal/storage.rb"
5
+ require 'ya2yaml'
6
+ require File.dirname(__FILE__) +"/memory_repository.rb"
7
+ require File.dirname(__FILE__) +"/domain_object_cache_item.rb"
8
+ class Repository
9
+ attr_accessor :use_cache
10
+ attr_accessor :storage
11
+ def initialize(
12
+ sdb_domain_prefix,#MyDevPayApp
13
+ clob_bucket,
14
+ aws_key_id,
15
+ aws_secret_key,
16
+ memcache_servers = nil ,
17
+ a_storage=nil,
18
+ append_table_to_domain=true,
19
+ options={}
20
+
21
+ )
22
+
23
+ @use_cache=true
24
+ @storage=a_storage
25
+ @storage||=Storage.new(aws_key_id,aws_secret_key,memcache_servers)
26
+ @sdb_domain_prefix = sdb_domain_prefix
27
+ @clob_bucket = clob_bucket
28
+ @memcache_servers = memcache_servers
29
+ @aws_key_id = aws_key_id
30
+ @aws_secret_key = aws_secret_key
31
+ @append_table_to_domain=append_table_to_domain
32
+ @logger = options[:logger]
33
+ if !@logger
34
+ @logger = Logger.new(STDOUT)
35
+ @logger.level = Logger::ERROR
36
+ end
37
+
38
+ @sdb=AwsSdb::Service.new(:access_key_id=>aws_key_id,:secret_access_key=>aws_secret_key,:url=>"http://sdb.amazonaws.com",:logger=>@logger)
39
+ @session_cache=MemoryRepository.new
40
+
41
+ #create_domain()
42
+ end
43
+
44
+ def clear_session_cache
45
+ @session_cache.clear
46
+ end
47
+ def make_clob_key(table_name,primary_key,clob_name)
48
+ return "clobs/#{table_name}/#{CGI.escape(primary_key.to_s)}/#{clob_name}"
49
+ end
50
+ def make_cache_key(table_name,primary_key)
51
+ return "cached_objects/#{table_name}/#{CGI.escape(primary_key.to_s)}"
52
+ end
53
+ def get_clob(table_name,primary_key,clob_name)
54
+ return @storage.get(@clob_bucket,make_clob_key(table_name,primary_key,clob_name))
55
+
56
+ end
57
+ def save(table_name, primary_key, attributes)
58
+ @session_cache.save(table_name,primary_key,attributes)
59
+ formatted_attributes={}
60
+ attributes.each do |description,value|
61
+ if value || description.value_type==:boolean
62
+ if description.is_clob
63
+ @storage.put(
64
+ @clob_bucket,
65
+ make_clob_key(table_name,primary_key,description.name),
66
+ value.to_s,
67
+ {})
68
+ else
69
+ formatted_attributes[description.name]=description.format_for_sdb(value)
70
+ end
71
+ end
72
+ end
73
+
74
+ put_attributes(table_name,primary_key, formatted_attributes )
75
+ # put_into_cache(table_name, primary_key, formatted_attributes)
76
+
77
+ end
78
+ # def put_into_cache(table_name, primary_key, formatted_attributes)
79
+ # if @use_cache
80
+ # cacheItem=DomainObjectCacheItem.new(table_name, primary_key, formatted_attributes)
81
+ #
82
+ # yaml=cacheItem.ya2yaml(:syck_compatible => true)
83
+ #
84
+ # @storage.put(
85
+ # @clob_bucket,
86
+ # make_cache_key(table_name,primary_key),
87
+ # yaml ,
88
+ # {})
89
+ # end
90
+ # end
91
+ def create_domain
92
+ 20.times do |i|
93
+ begin
94
+ @sdb.create_domain(@sdb_domain)
95
+ return
96
+
97
+ rescue => e
98
+ s= "#{e.message}\n#{e.backtrace}"
99
+ @logger.warn(s) if @logger
100
+ sleep(i*i)
101
+
102
+ end
103
+ end
104
+
105
+ end
106
+ def put_attributes(table_name,primary_key, formatted_attributes,options={})
107
+ 20.times do |i|
108
+ begin
109
+ @sdb.put_attributes(make_domain_name(table_name),primary_key.to_s, formatted_attributes, true )
110
+ return
111
+
112
+ rescue Exception => e
113
+ s= "#{e.message}\n#{e.backtrace}"
114
+ @logger.warn(s) if @logger
115
+
116
+ sleep(i*i)
117
+ end
118
+ end
119
+
120
+ end
121
+ def extend_query(query,new_clause)
122
+ if query.length>0
123
+ query << " intersection "
124
+ end
125
+
126
+ query << new_clause
127
+ end
128
+ def escape_quotes(value)
129
+ value.gsub( "'","\\'")
130
+ end
131
+ def query_ids(table_name,attribute_descriptions,options={})
132
+
133
+ if options.has_key?(:limit) and !options.has_key?(:order_by)
134
+ session_cache_result=@session_cache.query_ids(table_name,attribute_descriptions,options)
135
+ if options[:limit]==session_cache_result.length
136
+ return session_cache_result
137
+ end
138
+ end
139
+ query=""
140
+
141
+ if options
142
+ if options.has_key?(:query)
143
+ extend_query(query,"["+options[:query]+"]")
144
+ end
145
+ if options.has_key?(:params)
146
+ options[:params].each do |key,value|
147
+ got_something=false
148
+ if attribute_descriptions.has_key?(key)
149
+ if value==:NOT_NULL
150
+ got_something=true
151
+ extend_query(query," ['#{key}' starts-with '']")
152
+ end
153
+ if value==:NULL
154
+ got_something=true
155
+ extend_query(query," not ['#{key}' starts-with '']")
156
+ end
157
+ if value.respond_to?(:less_than) && value.less_than
158
+ got_something=true
159
+ extend_query(query," ['#{key}' < '#{escape_quotes(attribute_descriptions[key].format_for_sdb_single( value.less_than))}']")
160
+ end
161
+ if value.respond_to?(:greater_than) && value.greater_than
162
+ got_something=true
163
+ extend_query(query," ['#{key}' > '#{escape_quotes( attribute_descriptions[key].format_for_sdb_single( value.greater_than))}']")
164
+ end
165
+ if value.respond_to?(:less_than_or_equal_to) && value.less_than_or_equal_to
166
+ got_something=true
167
+ extend_query(query,"['#{key}' <= '#{escape_quotes( attribute_descriptions[key].format_for_sdb_single( value.less_than_or_equal_to))}']")
168
+ end
169
+ if value.respond_to?(:greater_than_or_equal_to) && value.greater_than_or_equal_to
170
+ got_something=true
171
+ extend_query(query," ['#{key}' >= '#{escape_quotes(attribute_descriptions[key].format_for_sdb_single( value.greater_than_or_equal_to))}']")
172
+ end
173
+ if value==false
174
+ got_something=true
175
+ extend_query(query," ['#{key}' != 'true' ]")
176
+ end
177
+ if !got_something
178
+ extend_query(query," ['#{key}' = '#{escape_quotes( attribute_descriptions[key].format_for_sdb_single(value))}']")
179
+ end
180
+ else
181
+ #it must be formatted already. likely an index
182
+ extend_query(query,"['#{key}' = '#{escape_quotes value}']")
183
+ end
184
+ end
185
+ end
186
+ if options.has_key?(:order_by) && options[:order_by]
187
+ clause=" ['#{options[:order_by]}' starts-with ''] sort '#{options[:order_by]}' "
188
+ if options.has_key?(:order) and options[:order]==:descending
189
+ clause<<" desc "
190
+ end
191
+ extend_query(query,clause)
192
+ end
193
+ if options.has_key?(:conditions)
194
+ options[:conditions].each do |condition|
195
+
196
+ extend_query(query," [ "+condition.to_sdb_query()+"]")
197
+ end
198
+ end
199
+
200
+ end
201
+
202
+ max=250
203
+ if options[:limit]
204
+ max=options[:limit].to_i
205
+
206
+ end
207
+ page_size=max>250?250:max
208
+ sdb_results,token=sdb_query(table_name,query,page_size)
209
+
210
+ while !(token.nil? || token.empty? || sdb_results.length>=max)
211
+ page_size=max- sdb_results.length
212
+ page_size=page_size>250?250:page_size
213
+ partial_results,token=sdb_query(table_name,query,page_size,token)
214
+ sdb_results.concat( partial_results)
215
+ end
216
+ sdb_results
217
+
218
+
219
+ return sdb_results
220
+ end
221
+ def query(table_name,attribute_descriptions,options)
222
+ ids=query_ids(table_name,attribute_descriptions,options)
223
+ result=[]
224
+ ids.each do |primary_key|
225
+ if primary_key
226
+ (0..4).each do |try_count|
227
+ this_one=find_one(table_name,primary_key,attribute_descriptions)
228
+ if this_one
229
+ result<<this_one
230
+ break
231
+ else
232
+ #sdb query just told us it was there so keep trying
233
+ sleep(try_count*try_count)
234
+ end
235
+ end
236
+ else
237
+ @logger.error("blank primary key")
238
+ end
239
+ end
240
+ if options and options[:order_by]
241
+ result.sort! do |a,b|
242
+ a_value=a[options[:order_by]]
243
+ b_value=b[options[:order_by]]
244
+ if options[:order] && options[:order]!=:ascending
245
+ if !a_value
246
+ 1
247
+ else
248
+ if b_value
249
+ b_value <=> a_value
250
+ else
251
+ -1
252
+ end
253
+ end
254
+ else
255
+ if !b_value
256
+ 1
257
+ else
258
+ if a_value
259
+ a_value <=> b_value
260
+ else
261
+ -1
262
+ end
263
+ end
264
+ end
265
+ end
266
+ end
267
+ if options[:limit] && result.length>options[:limit]
268
+ result=result[0..(options[:limit]-1)]
269
+ end
270
+ return result
271
+ end
272
+ def find_one(table_name, primary_key,attribute_descriptions)#, non_clob_attribute_names, clob_attribute_names)
273
+ session_cache_result=@session_cache.find_one(table_name, primary_key,attribute_descriptions)
274
+ return session_cache_result if session_cache_result
275
+ # if @use_cache
276
+ # yaml=@storage.get(@clob_bucket,make_cache_key(table_name,primary_key))
277
+ # if yaml
278
+ # result=YAML::load( yaml)
279
+ # if result.respond_to?(:non_clob_attributes) && result.non_clob_attributes!=nil
280
+ # return parse_attributes(attribute_descriptions, result.non_clob_attributes)
281
+ # end
282
+ #
283
+ # end
284
+ # end
285
+ attributes=parse_attributes(attribute_descriptions,sdb_get_attributes(table_name,primary_key))
286
+ if attributes
287
+ attributes[:primary_key]=primary_key
288
+ #put_into_cache(table_name, primary_key, attributes)
289
+ end
290
+
291
+ attributes
292
+ end
293
+ def make_domain_name(table_name)
294
+ if @append_table_to_domain
295
+ @sdb_domain_prefix+"_"+table_name
296
+ else
297
+ @sdb_domain_prefix
298
+ end
299
+ end
300
+ def sdb_get_attributes(table_name,primary_key)
301
+
302
+ @logger.debug( "SDB get_attributes #{table_name} : #{primary_key}") if @logger
303
+
304
+ 20.times do |i|
305
+ begin
306
+ return @sdb.get_attributes(make_domain_name(table_name), primary_key)
307
+ rescue Exception => e
308
+ s= "#{e.message}\n#{e.backtrace}"
309
+ @logger.warn(s) if @logger
310
+
311
+ sleep(i*i)
312
+ ensure
313
+
314
+ end
315
+ end
316
+
317
+ end
318
+ def sdb_query(table_name,query,max,token=nil)
319
+
320
+ @logger.debug( "SDB query:#{table_name}(#{max}) : #{query} #{token}" ) if @logger
321
+ puts "#{table_name} #{query} (#{max}) #{token}"
322
+ 20.times do |i|
323
+ begin
324
+ return @sdb.query(make_domain_name(table_name),query,max,token)
325
+
326
+ rescue Exception => e
327
+ s= "#{e.message}\n#{e.backtrace}"
328
+ @logger.error(s) if @logger
329
+
330
+ sleep(i*i)
331
+ ensure
332
+
333
+ end
334
+ end
335
+
336
+ end
337
+
338
+ def parse_attributes(attribute_descriptions,attributes)
339
+ if !attributes || attributes.length==0
340
+ return nil
341
+ end
342
+ parsed_attributes={}
343
+ attribute_descriptions.each do |attribute_name,attribute_description|
344
+ value=attributes[attribute_name.to_sym]
345
+ if !value
346
+ value=attributes[attribute_name]
347
+ end
348
+ #sdb attributes are often array of one
349
+ if !attribute_description.is_collection && value.respond_to?(:flatten) && value.length==1
350
+ value=value[0]
351
+ end
352
+ parsed_attributes[attribute_name.to_sym]=attribute_description.parse_from_sdb(value)
353
+ end
354
+ parsed_attributes
355
+ end
356
+ def destroy(table_name, primary_key)
357
+ @sdb.delete_attributes(make_domain_name(table_name), primary_key)
358
+ if @use_cache
359
+ @storage.delete(@clob_bucket,make_cache_key(table_name,primary_key))
360
+ end
361
+ end
362
+ #parse date in yyyy-mm-dd format
363
+
364
+ end
365
+
366
+ end