merb-cache 0.9.2

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,88 @@
1
+ module Merb::Cache::DatabaseStore::ActiveRecord
2
+ # Module that provides ActiveRecord support for the database backend
3
+
4
+ # The cache model migration
5
+ class CacheMigration < ActiveRecord::Migration
6
+ def self.up
7
+ create_table (Merb::Controller._cache.config[:table_name]), :primary_key => :ckey do |t|
8
+ t.column :ckey, :string
9
+ t.column :data, :text
10
+ t.datetime :expire, :default => nil
11
+ end
12
+ end
13
+
14
+ def self.down
15
+ drop_table Merb::Controller._cache.config[:table_name]
16
+ end
17
+ end
18
+
19
+ # The cache model
20
+ class CacheModel < ActiveRecord::Base
21
+ set_table_name Merb::Controller._cache.config[:table_name]
22
+
23
+ # Fetch data from the database using the specified key
24
+ # The entry is deleted if it has expired
25
+ #
26
+ # ==== Parameter
27
+ # key<Sting>:: The key identifying the cache entry
28
+ #
29
+ # ==== Returns
30
+ # data<String, NilClass>::
31
+ # nil is returned whether the entry expired or was not found
32
+ def self.cache_get(key)
33
+ if entry = self.find(:first, :conditions => ["ckey=?", key])
34
+ return entry.data if entry.expire.nil? || Time.now < entry.expire
35
+ self.expire(key)
36
+ end
37
+ nil
38
+ end
39
+
40
+ # Store data to the database using the specified key
41
+ #
42
+ # ==== Parameters
43
+ # key<Sting>:: The key identifying the cache entry
44
+ # data<String>:: The data to be put in cache
45
+ # expire<~minutes>::
46
+ # The number of minutes (from now) the cache should persist
47
+ # get<Boolean>::
48
+ # used internally to behave like this
49
+ # - when set to true, perform update_or_create on the cache entry
50
+ # - when set to false, force creation of the cache entry
51
+ def self.cache_set(key, data, expire = nil, get = true)
52
+ attributes = {:ckey => key, :data => data, :expire => expire }
53
+ if get
54
+ entry = self.find(:first, :conditions => ["ckey=?",key])
55
+ entry.nil? ? self.create(attributes) : entry.update_attributes(attributes)
56
+ else
57
+ self.create(attributes)
58
+ end
59
+ true
60
+ end
61
+
62
+ # Expire the cache entry identified by the given key
63
+ #
64
+ # ==== Parameter
65
+ # key<Sting>:: The key identifying the cache entry
66
+ def self.expire(key)
67
+ self.delete_all(["ckey=?", key])
68
+ end
69
+
70
+ # Expire the cache entries matching the given key
71
+ #
72
+ # ==== Parameter
73
+ # key<Sting>:: The key matching the cache entries
74
+ def self.expire_match(key)
75
+ self.delete_all(["ckey like ?", key + "%"])
76
+ end
77
+
78
+ # Expire all the cache entries
79
+ def self.expire_all
80
+ self.delete_all
81
+ end
82
+
83
+ # Perform auto-migration in case the table is unknown in the database
84
+ def self.check_table
85
+ CacheMigration.up unless self.table_exists?
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,79 @@
1
+ module Merb::Cache::DatabaseStore::DataMapper
2
+ # Module that provides DataMapper support for the database backend
3
+
4
+ # The cache model
5
+ class CacheModel < DataMapper::Base
6
+ set_table_name Merb::Controller._cache.config[:table_name]
7
+ property :ckey, :string, :length => 255, :lazy => false, :key => true
8
+ property :data, :text, :lazy => false
9
+ property :expire, :datetime, :default => nil
10
+
11
+ # Fetch data from the database using the specified key
12
+ # The entry is deleted if it has expired
13
+ #
14
+ # ==== Parameter
15
+ # key<Sting>:: The key identifying the cache entry
16
+ #
17
+ # ==== Returns
18
+ # data<String, NilClass>::
19
+ # nil is returned whether the entry expired or was not found
20
+ def self.cache_get(key)
21
+ if entry = self.first(key)
22
+ return entry.data if entry.expire.nil? || DateTime.now < entry.expire
23
+ entry.destroy!
24
+ end
25
+ nil
26
+ end
27
+
28
+ # Store data to the database using the specified key
29
+ #
30
+ # ==== Parameters
31
+ # key<Sting>:: The key identifying the cache entry
32
+ # data<String>:: The data to be put in cache
33
+ # expire<~minutes>::
34
+ # The number of minutes (from now) the cache should persist
35
+ # get<Boolean>::
36
+ # used internally to behave like this:
37
+ # - when set to true, perform update_or_create on the cache entry
38
+ # - when set to false, force creation of the cache entry
39
+ def self.cache_set(key, data, expire = nil, get = true)
40
+ attributes = {:ckey => key, :data => data,
41
+ :expire => expire.nil? ? nil : expire.to_s_db }
42
+ if get
43
+ entry = self.first(key)
44
+ entry.nil? ? self.create(attributes) : entry.update_attributes(attributes)
45
+ else
46
+ self.create(attributes)
47
+ end
48
+ true
49
+ end
50
+
51
+ # Expire the cache entry identified by the given key
52
+ #
53
+ # ==== Parameter
54
+ # key<Sting>:: The key identifying the cache entry
55
+ def self.expire(key)
56
+ entry = self.first(key)
57
+ entry.destroy! unless entry.nil?
58
+ end
59
+
60
+ # Expire the cache entries matching the given key
61
+ #
62
+ # ==== Parameter
63
+ # key<Sting>:: The key matching the cache entries
64
+ def self.expire_match(key)
65
+ #FIXME
66
+ database.execute("DELETE FROM #{self.table.name} WHERE ckey LIKE '#{key}%'")
67
+ end
68
+
69
+ # Expire all the cache entries
70
+ def self.expire_all
71
+ self.truncate!
72
+ end
73
+
74
+ # Perform auto-migration in case the table is unknown in the database
75
+ def self.check_table
76
+ self.auto_migrate! unless self.table.exists?
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,78 @@
1
+ module Merb::Cache::DatabaseStore::Sequel
2
+ # Module that provides Sequel support for the database backend
3
+
4
+ # The cache model
5
+ class CacheModel < Sequel::Model(Merb::Controller._cache.config[:table_name].to_sym)
6
+ set_schema do
7
+ primary_key :id
8
+ varchar :ckey, :index => true
9
+ varchar :data
10
+ timestamp :expire, :default => nil
11
+ end
12
+
13
+ # Fetch data from the database using the specified key
14
+ # The entry is deleted if it has expired
15
+ #
16
+ # ==== Parameter
17
+ # key<Sting>:: The key identifying the cache entry
18
+ #
19
+ # ==== Returns
20
+ # data<String, NilClass>::
21
+ # nil is returned whether the entry expired or was not found
22
+ def self.cache_get(key)
23
+ if entry = self.filter(:ckey => key).single_record(:limit => 1)
24
+ return entry.data if entry.expire.nil? || Time.now < entry.expire
25
+ self.expire(key)
26
+ end
27
+ nil
28
+ end
29
+
30
+ # Store data to the database using the specified key
31
+ #
32
+ # ==== Parameters
33
+ # key<Sting>:: The key identifying the cache entry
34
+ # data<String>:: The data to be put in cache
35
+ # expire<~minutes>::
36
+ # The number of minutes (from now) the cache should persist
37
+ # get<Boolean>::
38
+ # used internally to behave like this
39
+ # - when set to true, perform update_or_create on the cache entry
40
+ # - when set to false, force creation of the cache entry
41
+ def self.cache_set(key, data, expire = nil, get = true)
42
+ attributes = {:ckey => key, :data => data, :expire => expire }
43
+ if get
44
+ entry = self.filter(:ckey => key).single_record(:limit => 1)
45
+ entry.nil? ? self.create(attributes) : entry.set(attributes)
46
+ else
47
+ self.create(attributes)
48
+ end
49
+ true
50
+ end
51
+
52
+ # Expire the cache entry identified by the given key
53
+ #
54
+ # ==== Parameter
55
+ # key<Sting>:: The key identifying the cache entry
56
+ def self.expire(key)
57
+ self.filter(:ckey => key).delete
58
+ end
59
+
60
+ # Expire the cache entries matching the given key
61
+ #
62
+ # ==== Parameter
63
+ # key<Sting>:: The key matching the cache entries
64
+ def self.expire_match(key)
65
+ self.filter{:ckey.like key + "%"}.delete
66
+ end
67
+
68
+ # Expire all the cache entries
69
+ def self.expire_all
70
+ self.delete_all
71
+ end
72
+
73
+ # Perform auto-migration in case the table is unknown in the database
74
+ def self.check_table
75
+ self.create_table unless self.table_exists?
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,144 @@
1
+ class Merb::Cache::DatabaseStore
2
+ # Provides the database cache store for merb-cache
3
+
4
+ def initialize
5
+ @config = Merb::Controller._cache.config
6
+ prepare
7
+ end
8
+
9
+ class OrmNotFound < Exception #:nodoc:
10
+ def initialize
11
+ super("No valid ORM found (did you specify use_orm in init.rb?)")
12
+ end
13
+ end
14
+
15
+ # Requires the ORM at startup, raising an OrmNotFound exception if
16
+ # the backend is not found
17
+ Merb::Controller._cache.config[:table_name] ||= "merb_cache"
18
+ if defined?(Merb::Orms::ActiveRecord)
19
+ require "merb-cache/cache-store/database-activerecord.rb"
20
+ include Merb::Cache::DatabaseStore::ActiveRecord
21
+ elsif defined?(Merb::Orms::DataMapper)
22
+ require "merb-cache/cache-store/database-datamapper.rb"
23
+ include Merb::Cache::DatabaseStore::DataMapper
24
+ elsif defined?(Merb::Orms::Sequel)
25
+ require "merb-cache/cache-store/database-sequel.rb"
26
+ include Merb::Cache::DatabaseStore::Sequel
27
+ else
28
+ raise OrmNotFound
29
+ end
30
+
31
+ # This method is there to ensure minimal requirements are met
32
+ # (file permissions, table exists, connected to server, ...)
33
+ def prepare
34
+ CacheModel.check_table
35
+ true
36
+ end
37
+
38
+ # Checks whether a cache entry exists
39
+ #
40
+ # ==== Parameter
41
+ # key<String>:: The key identifying the cache entry
42
+ #
43
+ # ==== Returns
44
+ # true if the cache entry exists, false otherwise
45
+ def cached?(key)
46
+ not CacheModel.cache_get(key).nil?
47
+ end
48
+
49
+ # Capture or restore the data in cache.
50
+ # If the cache entry expired or does not exist, the data are taken
51
+ # from the execution of the block, marshalled and stored in cache.
52
+ # Otherwise, the data are loaded from the cache and returned unmarshalled
53
+ #
54
+ # ==== Parameters
55
+ # _controller<Merb::Controller>:: The instance of the current controller
56
+ # key<String>:: The key identifying the cache entry
57
+ # from_now<~minutes>::
58
+ # The number of minutes (from now) the cache should persist
59
+ # &block:: The template to be used or not
60
+ #
61
+ # ==== Additional information
62
+ # When fetching data (the cache entry exists and has not expired)
63
+ # The data are loaded from the cache and returned unmarshalled.
64
+ # Otherwise:
65
+ # The controller is used to capture the rendered template (from the block).
66
+ # It uses the capture_#{engine} and concat_#{engine} methods to do so.
67
+ # The captured data are then marshalled and stored.
68
+ def cache(_controller, key, from_now = nil, &block)
69
+ _data = CacheModel.cache_get(key)
70
+ if _data.nil?
71
+ _expire = from_now ? from_now.minutes.from_now : nil
72
+ _data = _controller.send(:capture, &block)
73
+ CacheModel.cache_set(key, Marshal.dump(_data), _expire, false)
74
+ else
75
+ _data = Marshal.load(_data)
76
+ end
77
+ _controller.send(:concat, _data, block.binding)
78
+ true
79
+ end
80
+
81
+ # Store data to the database using the specified key
82
+ #
83
+ # ==== Parameters
84
+ # key<Sting>:: The key identifying the cache entry
85
+ # data<String>:: The data to be put in cache
86
+ # from_now<~minutes>::
87
+ # The number of minutes (from now) the cache should persist
88
+ def cache_set(key, data, from_now = nil)
89
+ _expire = from_now ? from_now.minutes.from_now : nil
90
+ CacheModel.cache_set(key, Marshal.dump(data), _expire)
91
+ Merb.logger.info("cache: set (#{key})")
92
+ true
93
+ end
94
+
95
+ # Fetch data from the database using the specified key
96
+ # The entry is deleted if it has expired
97
+ #
98
+ # ==== Parameter
99
+ # key<Sting>:: The key identifying the cache entry
100
+ #
101
+ # ==== Returns
102
+ # data<String, NilClass>::
103
+ # nil is returned whether the entry expired or was not found
104
+ def cache_get(key)
105
+ data = CacheModel.cache_get(key)
106
+ Merb.logger.info("cache: #{data.nil? ? "miss" : "hit"} (#{key})")
107
+ data.nil? ? nil : Marshal.load(data)
108
+ end
109
+
110
+ # Expire the cache entry identified by the given key
111
+ #
112
+ # ==== Parameter
113
+ # key<Sting>:: The key identifying the cache entry
114
+ def expire(key)
115
+ CacheModel.expire(key)
116
+ Merb.logger.info("cache: expired (#{key})")
117
+ true
118
+ end
119
+
120
+ # Expire the cache entries matching the given key
121
+ #
122
+ # ==== Parameter
123
+ # key<Sting>:: The key matching the cache entries
124
+ def expire_match(key)
125
+ CacheModel.expire_match(key)
126
+ Merb.logger.info("cache: expired matching (#{key})")
127
+ true
128
+ end
129
+
130
+ # Expire all the cache entries
131
+ def expire_all
132
+ CacheModel.expire_all
133
+ Merb.logger.info("cache: expired all")
134
+ true
135
+ end
136
+
137
+ # Gives info on the current cache store
138
+ #
139
+ # ==== Returns
140
+ # The type of the current cache store
141
+ def cache_store_type
142
+ "database"
143
+ end
144
+ end
@@ -0,0 +1,106 @@
1
+ class Merb::Cache::DummyStore
2
+ # Provides dummy cache store for merb-cache
3
+
4
+ def initialize
5
+ @config = Merb::Controller._cache.config
6
+ prepare
7
+ end
8
+
9
+ # This method is there to ensure minimal requirements are met
10
+ # (directories are accessible, table exists, connected to server, ...)
11
+ def prepare
12
+ true
13
+ end
14
+
15
+ # Checks whether a cache entry exists
16
+ #
17
+ # ==== Parameter
18
+ # key<String>:: The key identifying the cache entry
19
+ #
20
+ # ==== Returns
21
+ # true if the cache entry exists, false otherwise
22
+ def cached?(key)
23
+ false
24
+ end
25
+
26
+ # Capture or restore the data in cache.
27
+ # If the cache entry expired or does not exist, the data are taken
28
+ # from the execution of the block, marshalled and stored in cache.
29
+ # Otherwise, the data are loaded from the cache and returned unmarshalled
30
+ #
31
+ # ==== Parameters
32
+ # _controller<Merb::Controller>:: The instance of the current controller
33
+ # key<String>:: The key identifying the cache entry
34
+ # from_now<~minutes>::
35
+ # The number of minutes (from now) the cache should persist
36
+ # &block:: The template to be used or not
37
+ #
38
+ # ==== Additional information
39
+ # When fetching data (the cache entry exists and has not expired)
40
+ # The data are loaded from the cache and returned unmarshalled.
41
+ # Otherwise:
42
+ # The controller is used to capture the rendered template (from the block).
43
+ # It uses the capture_#{engine} and concat_#{engine} methods to do so.
44
+ # The captured data are then marshalled and stored.
45
+ def cache(_controller, key, from_now = nil, &block)
46
+ _data = _controller.send(:capture, &block)
47
+ _controller.send(:concat, _data, block.binding)
48
+ true
49
+ end
50
+
51
+ # Store data to memcache using the specified key
52
+ #
53
+ # ==== Parameters
54
+ # key<Sting>:: The key identifying the cache entry
55
+ # data<String>:: The data to be put in cache
56
+ # from_now<~minutes>::
57
+ # The number of minutes (from now) the cache should persist
58
+ def cache_set(key, data, from_now = nil)
59
+ true
60
+ end
61
+
62
+ # Fetch data from memcache using the specified key
63
+ # The entry is deleted if it has expired
64
+ #
65
+ # ==== Parameter
66
+ # key<Sting>:: The key identifying the cache entry
67
+ #
68
+ # ==== Returns
69
+ # data<String, NilClass>::
70
+ # nil is returned whether the entry expired or was not found
71
+ def cache_get(key)
72
+ nil
73
+ end
74
+
75
+ # Expire the cache entry identified by the given key
76
+ #
77
+ # ==== Parameter
78
+ # key<Sting>:: The key identifying the cache entry
79
+ def expire(key)
80
+ true
81
+ end
82
+
83
+ # Expire the cache entries matching the given key
84
+ #
85
+ # ==== Parameter
86
+ # key<Sting>:: The key matching the cache entries
87
+ #
88
+ # ==== Warning !
89
+ # This does not work in memcache.
90
+ def expire_match(key)
91
+ true
92
+ end
93
+
94
+ # Expire all the cache entries
95
+ def expire_all
96
+ true
97
+ end
98
+
99
+ # Gives info on the current cache store
100
+ #
101
+ # ==== Returns
102
+ # The type of the current cache store
103
+ def cache_store_type
104
+ "dummy"
105
+ end
106
+ end
@@ -0,0 +1,192 @@
1
+ class Merb::Cache::FileStore
2
+ # Provides the file cache store for merb-cache
3
+
4
+ def initialize
5
+ @config = Merb::Controller._cache.config
6
+ @config[:cache_directory] ||= Merb.root_path("tmp/cache")
7
+ # @config[:cache_action_directory] ||= Merb.dir_for(:public) / "cache"
8
+ prepare
9
+ end
10
+
11
+ class NotAccessible < Exception #:nodoc:
12
+ def initialize(message)
13
+ super("Cache directories are not readable/writeable (#{message})")
14
+ end
15
+ end
16
+
17
+ # This method is there to ensure minimal requirements are met
18
+ # (directories are accessible, table exists, connected to server, ...)
19
+ def prepare
20
+ unless File.readable?(@config[:cache_directory]) &&
21
+ File.writable?(@config[:cache_directory])
22
+ raise NotAccessible, @config[:cache_directory]
23
+ end
24
+ true
25
+ end
26
+
27
+ # Checks whether a cache entry exists
28
+ #
29
+ # ==== Parameter
30
+ # key<String>:: The key identifying the cache entry
31
+ #
32
+ # ==== Returns
33
+ # true if the cache entry exists, false otherwise
34
+ def cached?(key)
35
+ cache_file = @config[:cache_directory] / "#{key}.cache"
36
+ _data = _expire = nil
37
+ if File.file?(cache_file)
38
+ _data, _expire = Marshal.load(cache_read(cache_file))
39
+ return true if _expire.nil? || Time.now < _expire
40
+ FileUtils.rm_f(cache_file)
41
+ end
42
+ false
43
+ end
44
+
45
+ # Capture or restore the data in cache.
46
+ # If the cache entry expired or does not exist, the data are taken
47
+ # from the execution of the block, marshalled and stored in cache.
48
+ # Otherwise, the data are loaded from the cache and returned unmarshalled
49
+ #
50
+ # ==== Parameters
51
+ # _controller<Merb::Controller>:: The instance of the current controller
52
+ # key<String>:: The key identifying the cache entry
53
+ # from_now<~minutes>::
54
+ # The number of minutes (from now) the cache should persist
55
+ # &block:: The template to be used or not
56
+ #
57
+ # ==== Additional information
58
+ # When fetching data (the cache entry exists and has not expired)
59
+ # The data are loaded from the cache and returned unmarshalled.
60
+ # Otherwise:
61
+ # The controller is used to capture the rendered template (from the block).
62
+ # It uses the capture_#{engine} and concat_#{engine} methods to do so.
63
+ # The captured data are then marshalled and stored.
64
+ def cache(_controller, key, from_now = nil, &block)
65
+ cache_file = @config[:cache_directory] / "#{key}.cache"
66
+ _cache_hit = _data = _expire = nil
67
+
68
+ if File.file?(cache_file)
69
+ _data, _expire = Marshal.load(cache_read(cache_file))
70
+ _cache_hit = true if _expire.nil? || Time.now < _expire
71
+ end
72
+ unless _cache_hit
73
+ cache_directory = File.dirname(cache_file)
74
+ FileUtils.mkdir_p(cache_directory)
75
+ _expire = from_now ? from_now.minutes.from_now : nil
76
+ _data = _controller.send(:capture, &block)
77
+ cache_write(cache_file, Marshal.dump([_data, _expire]))
78
+ end
79
+ _controller.send(:concat, _data, block.binding)
80
+ true
81
+ end
82
+
83
+ # Store data to the file using the specified key
84
+ #
85
+ # ==== Parameters
86
+ # key<Sting>:: The key identifying the cache entry
87
+ # data<String>:: The data to be put in cache
88
+ # from_now<~minutes>::
89
+ # The number of minutes (from now) the cache should persist
90
+ def cache_set(key, data, from_now = nil)
91
+ cache_file = @config[:cache_directory] / "#{key}.cache"
92
+ cache_directory = File.dirname(cache_file)
93
+ FileUtils.mkdir_p(cache_directory)
94
+ _expire = from_now ? from_now.minutes.from_now : nil
95
+ cache_write(cache_file, Marshal.dump([data, _expire]))
96
+ Merb.logger.info("cache: set (#{key})")
97
+ true
98
+ end
99
+
100
+ # Fetch data from the file using the specified key
101
+ # The entry is deleted if it has expired
102
+ #
103
+ # ==== Parameter
104
+ # key<Sting>:: The key identifying the cache entry
105
+ #
106
+ # ==== Returns
107
+ # data<String, NilClass>::
108
+ # nil is returned whether the entry expired or was not found
109
+ def cache_get(key)
110
+ cache_file = @config[:cache_directory] / "#{key}.cache"
111
+ if File.file?(cache_file)
112
+ _data, _expire = Marshal.load(cache_read(cache_file))
113
+ if _expire.nil? || Time.now < _expire
114
+ Merb.logger.info("cache: hit (#{key})")
115
+ return _data
116
+ end
117
+ FileUtils.rm_f(cache_file)
118
+ end
119
+ Merb.logger.info("cache: miss (#{key})")
120
+ nil
121
+ end
122
+
123
+ # Expire the cache entry identified by the given key
124
+ #
125
+ # ==== Parameter
126
+ # key<Sting>:: The key identifying the cache entry
127
+ def expire(key)
128
+ FileUtils.rm_f(@config[:cache_directory] / "#{key}.cache")
129
+ Merb.logger.info("cache: expired (#{key})")
130
+ true
131
+ end
132
+
133
+ # Expire the cache entries matching the given key
134
+ #
135
+ # ==== Parameter
136
+ # key<Sting>:: The key matching the cache entries
137
+ def expire_match(key)
138
+ #files = Dir.glob(@config[:cache_directory] / "#{key}*.cache")
139
+ files = Dir.glob(@config[:cache_directory] / "#{key}*")
140
+ FileUtils.rm_rf(files)
141
+ Merb.logger.info("cache: expired matching (#{key})")
142
+ true
143
+ end
144
+
145
+ # Expire all the cache entries
146
+ def expire_all
147
+ FileUtils.rm_rf(Dir.glob("#{@config[:cache_directory]}/*"))
148
+ Merb.logger.info("cache: expired all")
149
+ true
150
+ end
151
+
152
+ # Gives info on the current cache store
153
+ #
154
+ # ==== Returns
155
+ # The type of the current cache store
156
+ def cache_store_type
157
+ "file"
158
+ end
159
+
160
+ private
161
+
162
+ # Read data from the file using exclusive lock
163
+ #
164
+ # ==== Parameters
165
+ # cache_file<String>:: The full path to the file
166
+ #
167
+ # ==== Returns
168
+ # _data<String>:: The data read from the file
169
+ def cache_read(cache_file)
170
+ _data = nil
171
+ File.open(cache_file, "r") do |cache_data|
172
+ cache_data.flock(File::LOCK_EX)
173
+ _data = cache_data.read
174
+ cache_data.flock(File::LOCK_UN)
175
+ end
176
+ _data
177
+ end
178
+
179
+ # Write data to the file using exclusive lock
180
+ #
181
+ # ==== Parameters
182
+ # cache_file<String>:: The full path to the file
183
+ # data<String>:: The data to be put in cache
184
+ def cache_write(cache_file, data)
185
+ File.open(cache_file, "w+") do |cache_data|
186
+ cache_data.flock(File::LOCK_EX)
187
+ cache_data.write(data)
188
+ cache_data.flock(File::LOCK_UN)
189
+ end
190
+ true
191
+ end
192
+ end