<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -228,9 +228,7 @@ a blanket rule for all users.
 
 Also note that at present Consent stores request history in memory, so memory usage will
 increase if you use long time periods. This feature has not been load-tested in production
-yet, but if people report problems I'll consider storing requests in SQLite. The other
-side-effect of in-memory storage is that the history is lost if you restart your app, but
-I'm working on a solution to that.
+yet, but if people report problems I'll consider storing requests in SQLite.
 
 
 == Helper methods</diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -17,7 +17,7 @@ module Consent
     end
     
     def throttle!(key, rate)
-      throttle = (@throttles[key.to_s] ||= Throttle.new)
+      throttle = (@throttles[key.to_s] ||= Throttle.new(inspect, key))
       throttle.rate = rate
       throttle
     end</diff>
      <filename>lib/consent/rule.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,26 @@
+require 'yaml'
+require 'fileutils'
+
 module Consent
   class Rule
     class Throttle
       
-      def initialize(rate = nil)
-        @rate, @times = rate, []
+      HISTORY_FILE = &quot;#{ RAILS_ROOT }/tmp/consent/#{ RAILS_ENV }.yml&quot;
+      
+      attr_reader :id, :key, :times
+      @@data = {}
+      
+      def initialize(id, key, rate = nil)
+        @id, @key, @rate, @times = id, key, rate, []
+        @@instances ||= []
+        @@instances &lt;&lt; self
+        
+        if data = ( ( @@data || {} )[id] || {} )[key]
+          @times = data.map do |time|
+            parts = time.split(/\D+/).map { |n| n.to_i }
+            Time.gm(*parts)
+          end
+        end
       end
       
       def rate=(rate)
@@ -25,6 +42,24 @@ module Consent
         @times.delete_if { |time| time &lt; cutoff }
       end
       
+      def self.to_yaml
+        (@@instances || []).inject({}) { |hash, throttle|
+          table = (hash[throttle.id] ||= {})
+          table[throttle.key] = throttle.times.map do |time|
+            time.strftime('%Y-%m-%d %H:%M:%S')
+          end
+          hash
+        }.to_yaml
+      end
+      
+      def self.dump
+        FileUtils.mkdir_p(File.dirname(HISTORY_FILE))
+        File.open(HISTORY_FILE, 'wb') { |file| file.write(Throttle.to_yaml) }
+      end
+      
+      Kernel.at_exit(&amp;method(:dump))
+      @@data = YAML.load(File.read(HISTORY_FILE)) if File.file?(HISTORY_FILE)
+      
     end
   end
 end</diff>
      <filename>lib/consent/rule/throttle.rb</filename>
    </modified>
    <modified>
      <diff>@@ -18,7 +18,10 @@ Consent.rules do
     false
   end
   
-  site*json { throttle params[:x], 3.per_second }
+  site*json do
+    throttle params[:x], 3.per_second
+    throttle &quot;extra: #{ params[:x] }&quot;, 3.per_second
+  end
   site.throttled { throttle params[:u], 3.per_second }
   site.throttled { deny if params[:ignore] }
   </diff>
      <filename>test/rules.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>b530d3bf4c669213d8d6c5761a42ac81fd461a6b</id>
    </parent>
  </parents>
  <author>
    <name>James Coglan</name>
    <email>jcoglan@googlemail.com</email>
  </author>
  <url>http://github.com/jcoglan/consent/commit/dfb2a82547d58b3074c9e8f87335524f8409ae68</url>
  <id>dfb2a82547d58b3074c9e8f87335524f8409ae68</id>
  <committed-date>2009-01-09T06:13:27-08:00</committed-date>
  <authored-date>2009-01-09T06:12:49-08:00</authored-date>
  <message>Dump throttle request data to disk when Ruby exits and reload from disk when the app comes back up. Enforces throttles across app restarts.</message>
  <tree>9c97ac55fcc20610f58e9e1ec847243b1e13d670</tree>
  <committer>
    <name>James Coglan</name>
    <email>jcoglan@googlemail.com</email>
  </committer>
</commit>
