Browse Source

Merge remote-tracking branch 'origin/master' into scenarios_contain_control_links

Andrew Cantino 9 years ago
parent
commit
9ad49fbf03

+ 4 - 0
.env.example

@@ -151,6 +151,10 @@ ENABLE_SECOND_PRECISION_SCHEDULE=false
 # at the expense of time accuracy.
 SCHEDULER_FREQUENCY=0.3
 
+# Specify the frequency with which the scheduler checks for and cleans up expired events.
+# You can use `m` for minutes, `h` for hours, and `d` for days.
+EVENT_EXPIRATION_CHECK=6h
+
 # Use Graphviz for generating diagrams instead of using Google Chart
 # Tools.  Specify a dot(1) command path built with SVG support
 # enabled.

+ 3 - 3
app/models/agent.rb

@@ -21,7 +21,7 @@ class Agent < ActiveRecord::Base
   SCHEDULES = %w[every_1m every_2m every_5m every_10m every_30m every_1h every_2h every_5h every_12h every_1d every_2d every_7d
                  midnight 1am 2am 3am 4am 5am 6am 7am 8am 9am 10am 11am noon 1pm 2pm 3pm 4pm 5pm 6pm 7pm 8pm 9pm 10pm 11pm never]
 
-  EVENT_RETENTION_SCHEDULES = [["Forever", 0], ["1 day", 1], *([2, 3, 4, 5, 7, 14, 21, 30, 45, 90, 180, 365].map {|n| ["#{n} days", n] })]
+  EVENT_RETENTION_SCHEDULES = [["Forever", 0], ['1 hour', 1.hour], ['6 hours', 6.hours], ["1 day", 1.day], *([2, 3, 4, 5, 7, 14, 21, 30, 45, 90, 180, 365].map {|n| ["#{n} days", n.days] })]
 
   attr_accessible :options, :memory, :name, :type, :schedule, :controller_ids, :control_target_ids, :disabled, :source_ids, :scenario_ids, :keep_events_for, :propagate_immediately, :drop_pending_events
 
@@ -130,14 +130,14 @@ class Agent < ActiveRecord::Base
   end
 
   def new_event_expiration_date
-    keep_events_for > 0 ? keep_events_for.days.from_now : nil
+    keep_events_for > 0 ? keep_events_for.seconds.from_now : nil
   end
 
   def update_event_expirations!
     if keep_events_for == 0
       events.update_all :expires_at => nil
     else
-      events.update_all "expires_at = " + rdbms_date_add("created_at", "DAY", keep_events_for.to_i)
+      events.update_all "expires_at = " + rdbms_date_add("created_at", "SECOND", keep_events_for.to_i)
     end
   end
 

+ 22 - 3
app/models/scenario_import.rb

@@ -150,7 +150,7 @@ class ScenarioImport
   def generate_diff
     @agent_diffs = (parsed_data['agents'] || []).map.with_index do |agent_data, index|
       # AgentDiff is defined at the end of this file.
-      agent_diff = AgentDiff.new(agent_data)
+      agent_diff = AgentDiff.new(agent_data, parsed_data['schema_version'])
       if existing_scenario
         # If this Agent exists already, update the AgentDiff with the local version's information.
         agent_diff.diff_with! existing_scenario.agents.find_by(:guid => agent_data['guid'])
@@ -192,14 +192,16 @@ class ScenarioImport
       end
     end
 
-    def initialize(agent_data)
+    def initialize(agent_data, schema_version)
       super()
+      @schema_version = schema_version
       @requires_merge = false
       self.agent = nil
       store! agent_data
     end
 
     BASE_FIELDS = %w[name schedule keep_events_for propagate_immediately disabled guid]
+    FIELDS_REQUIRING_TRANSLATION = %w[keep_events_for]
 
     def agent_exists?
       !!agent
@@ -217,10 +219,27 @@ class ScenarioImport
       self.type = FieldDiff.new(agent_data["type"].split("::").pop)
       self.options = FieldDiff.new(agent_data['options'] || {})
       BASE_FIELDS.each do |option|
-        self[option] = FieldDiff.new(agent_data[option]) if agent_data.has_key?(option)
+        if agent_data.has_key?(option)
+          value = agent_data[option]
+          value = send(:"translate_#{option}", value) if option.in?(FIELDS_REQUIRING_TRANSLATION)
+          self[option] = FieldDiff.new(value)
+        end
+      end
+    end
+
+    def translate_keep_events_for(old_value)
+      if schema_version < 1
+        # Was stored in days, now is stored in seconds.
+        old_value.to_i.days
+      else
+        old_value
       end
     end
 
+    def schema_version
+      (@schema_version || 0).to_i
+    end
+
     def diff_with!(agent)
       return unless agent.present?
 

+ 1 - 1
app/views/scenario_imports/_step_two.html.erb

@@ -14,7 +14,7 @@
         <span class='glyphicon glyphicon-warning-sign'></span>
         This Scenario already exists in your system. The import will update your existing
         <%= scenario_label(@scenario_import.existing_scenario) %> Scenario's title,
-        description and tag colors. Below you can customize how the individual agents get updated.
+        description, and tag colors. Below you can customize how the individual agents get updated.
       </div>
     <% end %>
 

+ 13 - 0
db/migrate/20150507153436_update_keep_events_for_to_be_in_seconds.rb

@@ -0,0 +1,13 @@
+class UpdateKeepEventsForToBeInSeconds < ActiveRecord::Migration
+  class Agent < ActiveRecord::Base; end
+
+  SECONDS_IN_DAY = 60 * 60 * 24
+
+  def up
+    Agent.update_all ['keep_events_for = keep_events_for * ?', SECONDS_IN_DAY]
+  end
+
+  def down
+    Agent.update_all ['keep_events_for = keep_events_for / ?', SECONDS_IN_DAY]
+  end
+end

+ 77 - 77
db/schema.rb

@@ -11,39 +11,39 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20140906030139) do
-
-  create_table "agent_logs", force: true do |t|
-    t.integer  "agent_id",                      null: false
-    t.text     "message",                       null: false, charset: "utf8mb4", collation: "utf8mb4_bin"
-    t.integer  "level",             default: 3, null: false
-    t.integer  "inbound_event_id"
-    t.integer  "outbound_event_id"
+ActiveRecord::Schema.define(version: 20150507153436) do
+
+  create_table "agent_logs", force: :cascade do |t|
+    t.integer  "agent_id",          limit: 4,                 null: false
+    t.text     "message",           limit: 65535,             null: false, charset: "utf8mb4", collation: "utf8mb4_bin"
+    t.integer  "level",             limit: 4,     default: 3, null: false
+    t.integer  "inbound_event_id",  limit: 4
+    t.integer  "outbound_event_id", limit: 4
     t.datetime "created_at"
     t.datetime "updated_at"
   end
 
-  create_table "agents", force: true do |t|
-    t.integer  "user_id"
-    t.text     "options",                                                               charset: "utf8mb4", collation: "utf8mb4_bin"
-    t.string   "type",                                                                                      collation: "utf8_bin"
-    t.string   "name",                                                                  charset: "utf8mb4", collation: "utf8mb4_bin"
-    t.string   "schedule",                                                                                  collation: "utf8_bin"
-    t.integer  "events_count",                             default: 0,     null: false
+  create_table "agents", force: :cascade do |t|
+    t.integer  "user_id",               limit: 4
+    t.text     "options",               limit: 65535,                                   charset: "utf8mb4", collation: "utf8mb4_bin"
+    t.string   "type",                  limit: 255,                                                         collation: "utf8_bin"
+    t.string   "name",                  limit: 255,                                     charset: "utf8mb4", collation: "utf8mb4_bin"
+    t.string   "schedule",              limit: 255,                                                         collation: "utf8_bin"
+    t.integer  "events_count",          limit: 4,          default: 0,     null: false
     t.datetime "last_check_at"
     t.datetime "last_receive_at"
-    t.integer  "last_checked_event_id"
+    t.integer  "last_checked_event_id", limit: 4
     t.datetime "created_at"
     t.datetime "updated_at"
-    t.text     "memory",                limit: 2147483647,                              charset: "utf8mb4", collation: "utf8mb4_bin"
+    t.text     "memory",                limit: 4294967295,                              charset: "utf8mb4", collation: "utf8mb4_bin"
     t.datetime "last_web_request_at"
-    t.integer  "keep_events_for",                          default: 0,     null: false
+    t.integer  "keep_events_for",       limit: 4,          default: 0,     null: false
     t.datetime "last_event_at"
     t.datetime "last_error_log_at"
-    t.boolean  "propagate_immediately",                    default: false, null: false
-    t.boolean  "disabled",                                 default: false, null: false
-    t.integer  "service_id"
-    t.string   "guid",                                                     null: false
+    t.boolean  "propagate_immediately", limit: 1,          default: false, null: false
+    t.boolean  "disabled",              limit: 1,          default: false, null: false
+    t.string   "guid",                  limit: 255,                        null: false, charset: "ascii",   collation: "ascii_bin"
+    t.integer  "service_id",            limit: 4
   end
 
   add_index "agents", ["guid"], name: "index_agents_on_guid", using: :btree
@@ -51,9 +51,9 @@ ActiveRecord::Schema.define(version: 20140906030139) do
   add_index "agents", ["type"], name: "index_agents_on_type", using: :btree
   add_index "agents", ["user_id", "created_at"], name: "index_agents_on_user_id_and_created_at", using: :btree
 
-  create_table "control_links", force: true do |t|
-    t.integer  "controller_id",     null: false
-    t.integer  "control_target_id", null: false
+  create_table "control_links", force: :cascade do |t|
+    t.integer  "controller_id",     limit: 4, null: false
+    t.integer  "control_target_id", limit: 4, null: false
     t.datetime "created_at"
     t.datetime "updated_at"
   end
@@ -61,25 +61,25 @@ ActiveRecord::Schema.define(version: 20140906030139) do
   add_index "control_links", ["control_target_id"], name: "index_control_links_on_control_target_id", using: :btree
   add_index "control_links", ["controller_id", "control_target_id"], name: "index_control_links_on_controller_id_and_control_target_id", unique: true, using: :btree
 
-  create_table "delayed_jobs", force: true do |t|
-    t.integer  "priority",                    default: 0
-    t.integer  "attempts",                    default: 0
+  create_table "delayed_jobs", force: :cascade do |t|
+    t.integer  "priority",   limit: 4,        default: 0
+    t.integer  "attempts",   limit: 4,        default: 0
     t.text     "handler",    limit: 16777215,             charset: "utf8mb4", collation: "utf8mb4_bin"
-    t.text     "last_error",                              charset: "utf8mb4", collation: "utf8mb4_bin"
+    t.text     "last_error", limit: 65535,                charset: "utf8mb4", collation: "utf8mb4_bin"
     t.datetime "run_at"
     t.datetime "locked_at"
     t.datetime "failed_at"
-    t.string   "locked_by"
-    t.string   "queue"
+    t.string   "locked_by",  limit: 255
+    t.string   "queue",      limit: 255
     t.datetime "created_at"
     t.datetime "updated_at"
   end
 
   add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority", using: :btree
 
-  create_table "events", force: true do |t|
-    t.integer  "user_id"
-    t.integer  "agent_id"
+  create_table "events", force: :cascade do |t|
+    t.integer  "user_id",    limit: 4
+    t.integer  "agent_id",   limit: 4
     t.decimal  "lat",                         precision: 15, scale: 10
     t.decimal  "lng",                         precision: 15, scale: 10
     t.text     "payload",    limit: 16777215,                           charset: "utf8mb4", collation: "utf8mb4_bin"
@@ -92,20 +92,20 @@ ActiveRecord::Schema.define(version: 20140906030139) do
   add_index "events", ["expires_at"], name: "index_events_on_expires_at", using: :btree
   add_index "events", ["user_id", "created_at"], name: "index_events_on_user_id_and_created_at", using: :btree
 
-  create_table "links", force: true do |t|
-    t.integer  "source_id"
-    t.integer  "receiver_id"
+  create_table "links", force: :cascade do |t|
+    t.integer  "source_id",            limit: 4
+    t.integer  "receiver_id",          limit: 4
     t.datetime "created_at"
     t.datetime "updated_at"
-    t.integer  "event_id_at_creation", default: 0, null: false
+    t.integer  "event_id_at_creation", limit: 4, default: 0, null: false
   end
 
   add_index "links", ["receiver_id", "source_id"], name: "index_links_on_receiver_id_and_source_id", using: :btree
   add_index "links", ["source_id", "receiver_id"], name: "index_links_on_source_id_and_receiver_id", using: :btree
 
-  create_table "scenario_memberships", force: true do |t|
-    t.integer  "agent_id",    null: false
-    t.integer  "scenario_id", null: false
+  create_table "scenario_memberships", force: :cascade do |t|
+    t.integer  "agent_id",    limit: 4, null: false
+    t.integer  "scenario_id", limit: 4, null: false
     t.datetime "created_at"
     t.datetime "updated_at"
   end
@@ -113,71 +113,71 @@ ActiveRecord::Schema.define(version: 20140906030139) do
   add_index "scenario_memberships", ["agent_id"], name: "index_scenario_memberships_on_agent_id", using: :btree
   add_index "scenario_memberships", ["scenario_id"], name: "index_scenario_memberships_on_scenario_id", using: :btree
 
-  create_table "scenarios", force: true do |t|
-    t.string   "name",                         null: false, charset: "utf8mb4", collation: "utf8mb4_bin"
-    t.integer  "user_id",                      null: false
+  create_table "scenarios", force: :cascade do |t|
+    t.string   "name",         limit: 255,                   null: false, charset: "utf8mb4", collation: "utf8mb4_bin"
+    t.integer  "user_id",      limit: 4,                     null: false
     t.datetime "created_at"
     t.datetime "updated_at"
-    t.text     "description",                               charset: "utf8mb4", collation: "utf8mb4_bin"
-    t.boolean  "public",       default: false, null: false
-    t.string   "guid",                         null: false, charset: "ascii",   collation: "ascii_bin"
-    t.string   "source_url"
-    t.string   "tag_bg_color"
-    t.string   "tag_fg_color"
+    t.text     "description",  limit: 65535,                              charset: "utf8mb4", collation: "utf8mb4_bin"
+    t.boolean  "public",       limit: 1,     default: false, null: false
+    t.string   "guid",         limit: 255,                   null: false, charset: "ascii",   collation: "ascii_bin"
+    t.string   "source_url",   limit: 255
+    t.string   "tag_bg_color", limit: 255
+    t.string   "tag_fg_color", limit: 255
   end
 
   add_index "scenarios", ["user_id", "guid"], name: "index_scenarios_on_user_id_and_guid", unique: true, using: :btree
 
-  create_table "services", force: true do |t|
-    t.integer  "user_id",                       null: false
-    t.string   "provider",                      null: false
-    t.string   "name",                          null: false
-    t.text     "token",                         null: false
-    t.text     "secret"
-    t.text     "refresh_token"
+  create_table "services", force: :cascade do |t|
+    t.integer  "user_id",       limit: 4,                     null: false
+    t.string   "provider",      limit: 255,                   null: false, collation: "utf8_general_ci"
+    t.string   "name",          limit: 255,                   null: false, collation: "utf8_general_ci"
+    t.text     "token",         limit: 65535,                 null: false, collation: "utf8_general_ci"
+    t.text     "secret",        limit: 65535,                              collation: "utf8_general_ci"
+    t.text     "refresh_token", limit: 65535,                              collation: "utf8_general_ci"
     t.datetime "expires_at"
-    t.boolean  "global",        default: false
-    t.text     "options"
+    t.boolean  "global",        limit: 1,     default: false
+    t.text     "options",       limit: 65535,                              collation: "utf8_general_ci"
     t.datetime "created_at"
     t.datetime "updated_at"
-    t.string   "uid"
+    t.string   "uid",           limit: 255,                                collation: "utf8_general_ci"
   end
 
   add_index "services", ["provider"], name: "index_services_on_provider", using: :btree
   add_index "services", ["uid"], name: "index_services_on_uid", using: :btree
   add_index "services", ["user_id", "global"], name: "index_services_on_user_id_and_global", using: :btree
 
-  create_table "user_credentials", force: true do |t|
-    t.integer  "user_id",                           null: false
-    t.string   "credential_name",                   null: false
-    t.text     "credential_value",                  null: false
+  create_table "user_credentials", force: :cascade do |t|
+    t.integer  "user_id",          limit: 4,                      null: false
+    t.string   "credential_name",  limit: 255,                    null: false
+    t.text     "credential_value", limit: 65535,                  null: false
     t.datetime "created_at"
     t.datetime "updated_at"
-    t.string   "mode",             default: "text", null: false, collation: "utf8_bin"
+    t.string   "mode",             limit: 255,   default: "text", null: false, collation: "utf8_bin"
   end
 
   add_index "user_credentials", ["user_id", "credential_name"], name: "index_user_credentials_on_user_id_and_credential_name", unique: true, using: :btree
 
-  create_table "users", force: true do |t|
-    t.string   "email",                              default: "",    null: false,                     collation: "utf8_bin"
-    t.string   "encrypted_password",                 default: "",    null: false, charset: "ascii",   collation: "ascii_bin"
-    t.string   "reset_password_token",                                                                collation: "utf8_bin"
+  create_table "users", force: :cascade do |t|
+    t.string   "email",                  limit: 255, default: "",    null: false,                     collation: "utf8_bin"
+    t.string   "encrypted_password",     limit: 255, default: "",    null: false, charset: "ascii",   collation: "ascii_bin"
+    t.string   "reset_password_token",   limit: 255,                                                  collation: "utf8_bin"
     t.datetime "reset_password_sent_at"
     t.datetime "remember_created_at"
-    t.integer  "sign_in_count",                      default: 0
+    t.integer  "sign_in_count",          limit: 4,   default: 0
     t.datetime "current_sign_in_at"
     t.datetime "last_sign_in_at"
-    t.string   "current_sign_in_ip"
-    t.string   "last_sign_in_ip"
+    t.string   "current_sign_in_ip",     limit: 255
+    t.string   "last_sign_in_ip",        limit: 255
     t.datetime "created_at"
     t.datetime "updated_at"
-    t.boolean  "admin",                              default: false, null: false
-    t.integer  "failed_attempts",                    default: 0
-    t.string   "unlock_token"
+    t.boolean  "admin",                  limit: 1,   default: false, null: false
+    t.integer  "failed_attempts",        limit: 4,   default: 0
+    t.string   "unlock_token",           limit: 255
     t.datetime "locked_at"
     t.string   "username",               limit: 191,                 null: false, charset: "utf8mb4", collation: "utf8mb4_unicode_ci"
-    t.string   "invitation_code",                                    null: false,                     collation: "utf8_bin"
-    t.integer  "scenario_count",                     default: 0,     null: false
+    t.string   "invitation_code",        limit: 255,                 null: false,                     collation: "utf8_bin"
+    t.integer  "scenario_count",         limit: 4,   default: 0,     null: false
   end
 
   add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree

+ 0 - 5
deployment/heroku/unicorn.rb

@@ -17,11 +17,6 @@ Thread.new do
 
     sleep 45
 
-    if ENV['DOMAIN']
-      force_ssl = ENV['FORCE_SSL'] == 'true'
-      Net::HTTP.get_response(URI((force_ssl ? "https://" : "http://") + ENV['DOMAIN']))
-    end
-
     begin
       Process.getpgid worker_pid
     rescue Errno::ESRCH

+ 1 - 0
lib/agents_exporter.rb

@@ -12,6 +12,7 @@ class AgentsExporter
 
   def as_json(opts = {})
     {
+      :schema_version => 1,
       :name => options[:name].presence || 'No name provided',
       :description => options[:description].presence || 'No description provided',
       :source_url => options[:source_url],

+ 1 - 1
lib/huginn_scheduler.rb

@@ -114,7 +114,7 @@ class HuginnScheduler
     end
 
     # Schedule event cleanup.
-    @rufus_scheduler.cron "0 0 * * * " + tzinfo_friendly_timezone do
+    @rufus_scheduler.every ENV['EVENT_EXPIRATION_CHECK'].presence || '6h' do
       cleanup_expired_events!
     end
 

+ 2 - 2
spec/fixtures/agents.yml

@@ -38,7 +38,7 @@ bob_weather_agent:
   schedule: "midnight"
   name: "SF Weather"
   guid: <%= SecureRandom.hex %>
-  keep_events_for: 45
+  keep_events_for: <%= 45.days %>
   options: <%= { :location => 94102, :lat => 37.779329, :lng => -122.41915, :api_key => 'test' }.to_json.inspect %>
 
 jane_weather_agent:
@@ -47,7 +47,7 @@ jane_weather_agent:
   schedule: "midnight"
   name: "SF Weather"
   guid: <%= SecureRandom.hex %>
-  keep_events_for: 30
+  keep_events_for: <%= 30.days %>
   options: <%= { :location => 94103, :lat => 37.779329, :lng => -122.41915, :api_key => 'test' }.to_json.inspect %>
 
 jane_rain_notifier_agent:

+ 1 - 0
spec/lib/agents_exporter_spec.rb

@@ -21,6 +21,7 @@ describe AgentsExporter do
       expect(data[:description]).to eq(description)
       expect(data[:source_url]).to eq(source_url)
       expect(data[:guid]).to eq(guid)
+      expect(data[:schema_version]).to eq(1)
       expect(data[:tag_fg_color]).to eq(tag_fg_color)
       expect(data[:tag_bg_color]).to eq(tag_bg_color)
       expect(Time.parse(data[:exported_at])).to be_within(2).of(Time.now.utc)

+ 11 - 11
spec/models/agent_spec.rb

@@ -546,11 +546,11 @@ describe Agent do
         expect(agent).to have(1).errors_on(:keep_events_for)
         agent.keep_events_for = ""
         expect(agent).to have(1).errors_on(:keep_events_for)
-        agent.keep_events_for = 5
+        agent.keep_events_for = 5.days.to_i
         expect(agent).to be_valid
         agent.keep_events_for = 0
         expect(agent).to be_valid
-        agent.keep_events_for = 365
+        agent.keep_events_for = 365.days.to_i
         expect(agent).to be_valid
 
         # Rails seems to call to_i on the input. This guards against future changes to that behavior.
@@ -564,7 +564,7 @@ describe Agent do
         @time = "2014-01-01 01:00:00 +00:00"
         time_travel_to @time do
           @agent = Agents::SomethingSource.new(:name => "something")
-          @agent.keep_events_for = 5
+          @agent.keep_events_for = 5.days
           @agent.user = users(:bob)
           @agent.save!
           @event = @agent.create_event :payload => { "hello" => "world" }
@@ -580,7 +580,7 @@ describe Agent do
           @agent.save!
 
           @agent.options[:foo] = "bar1"
-          @agent.keep_events_for = 5
+          @agent.keep_events_for = 5.days
           @agent.save!
         end
       end
@@ -590,7 +590,7 @@ describe Agent do
           time_travel_to @time do
             expect {
                 @agent.options[:foo] = "bar1"
-                @agent.keep_events_for = 3
+                @agent.keep_events_for = 3.days
                 @agent.save!
             }.to change { @event.reload.expires_at }
             expect(@event.expires_at.to_i).to be_within(2).of(3.days.from_now.to_i)
@@ -603,7 +603,7 @@ describe Agent do
 
           expect {
             @agent.options[:foo] = "bar2"
-            @agent.keep_events_for = 3
+            @agent.keep_events_for = 3.days
             @agent.save!
           }.to change { @event.reload.expires_at }
           expect(@event.expires_at.to_i).to be_within(60 * 61).of(1.days.from_now.to_i) # The larger time is to deal with daylight savings
@@ -635,7 +635,7 @@ describe Agent do
         @receiver = Agents::CannotBeScheduled.new(
           name: 'Agent',
           options: { foo: 'bar3' },
-          keep_events_for: 3,
+          keep_events_for: 3.days,
           propagate_immediately: true)
         @receiver.user = users(:bob)
         @receiver.sources << @sender
@@ -747,7 +747,7 @@ describe Agent do
 
       it "sets expires_at on created events" do
         event = agents(:jane_weather_agent).create_event :payload => { 'hi' => 'there' }
-        expect(event.expires_at.to_i).to be_within(5).of(agents(:jane_weather_agent).keep_events_for.days.from_now.to_i)
+        expect(event.expires_at.to_i).to be_within(5).of(agents(:jane_weather_agent).keep_events_for.seconds.from_now.to_i)
       end
     end
 
@@ -836,7 +836,7 @@ describe AgentDrop do
         },
       },
       schedule: 'every_1h',
-      keep_events_for: 2)
+      keep_events_for: 2.days)
     @wsa1.user = users(:bob)
     @wsa1.save!
 
@@ -853,7 +853,7 @@ describe AgentDrop do
         },
       },
       schedule: 'every_12h',
-      keep_events_for: 2)
+      keep_events_for: 2.days)
     @wsa2.user = users(:bob)
     @wsa2.save!
 
@@ -868,7 +868,7 @@ describe AgentDrop do
         matchers: [],
         skip_created_at: 'false',
       },
-      keep_events_for: 2,
+      keep_events_for: 2.days,
       propagate_immediately: true)
     @efa.user = users(:bob)
     @efa.sources << @wsa1 << @wsa2

+ 1 - 1
spec/models/agents/ftpsite_agent_spec.rb

@@ -9,7 +9,7 @@ describe Agents::FtpsiteAgent do
         'url' => "ftp://ftp.example.org/pub/releases/",
         'patterns' => ["example*.tar.gz"],
       }
-      @checker = Agents::FtpsiteAgent.new(:name => "Example", :options => @site, :keep_events_for => 2)
+      @checker = Agents::FtpsiteAgent.new(:name => "Example", :options => @site, :keep_events_for => 2.days)
       @checker.user = users(:bob)
       @checker.save!
     end

+ 1 - 1
spec/models/agents/imap_folder_agent_spec.rb

@@ -14,7 +14,7 @@ describe Agents::ImapFolderAgent do
         'conditions' => {
         }
       }
-      @checker = Agents::ImapFolderAgent.new(:name => 'Example', :options => @site, :keep_events_for => 2)
+      @checker = Agents::ImapFolderAgent.new(:name => 'Example', :options => @site, :keep_events_for => 2.days)
       @checker.user = users(:bob)
       @checker.save!
 

+ 2 - 2
spec/models/agents/website_agent_spec.rb

@@ -20,7 +20,7 @@ describe Agents::WebsiteAgent do
           'hovertext' => { 'css' => "#comic img", 'value' => "@title" }
         }
       }
-      @checker = Agents::WebsiteAgent.new(:name => "xkcd", :options => @valid_options, :keep_events_for => 2)
+      @checker = Agents::WebsiteAgent.new(:name => "xkcd", :options => @valid_options, :keep_events_for => 2.days)
       @checker.user = users(:bob)
       @checker.save!
     end
@@ -386,7 +386,7 @@ describe Agents::WebsiteAgent do
               'url' => { 'xpath' => '/feed/entry', 'value' => './link[1]/@href' },
               'thumbnail' => { 'xpath' => '/feed/entry', 'value' => './thumbnail/@url' },
             }
-          }, keep_events_for: 2)
+          }, keep_events_for: 2.days)
           @checker.user = users(:bob)
           @checker.save!
         end

+ 55 - 8
spec/models/scenario_import_spec.rb

@@ -30,7 +30,7 @@ describe ScenarioImport do
       :type => "Agents::WeatherAgent",
       :name => "a weather agent",
       :schedule => "5pm",
-      :keep_events_for => 14,
+      :keep_events_for => 14.days,
       :disabled => true,
       :guid => "a-weather-agent",
       :options => weather_agent_options
@@ -61,6 +61,7 @@ describe ScenarioImport do
   end
   let(:valid_parsed_data) do
     {
+      :schema_version => 1,
       :name => name,
       :description => description,
       :guid => guid,
@@ -204,7 +205,7 @@ describe ScenarioImport do
 
           expect(weather_agent.name).to eq("a weather agent")
           expect(weather_agent.schedule).to eq("5pm")
-          expect(weather_agent.keep_events_for).to eq(14)
+          expect(weather_agent.keep_events_for).to eq(14.days)
           expect(weather_agent.propagate_immediately).to be_falsey
           expect(weather_agent).to be_disabled
           expect(weather_agent.memory).to be_empty
@@ -228,6 +229,23 @@ describe ScenarioImport do
           }.to change { users(:bob).agents.count }.by(2)
         end
 
+        context "when the schema_version is less than 1" do
+          before do
+            valid_parsed_weather_agent_data[:keep_events_for] = 2
+            valid_parsed_data.delete(:schema_version)
+          end
+
+          it "translates keep_events_for from days to seconds" do
+            scenario_import.import
+            expect(scenario_import.errors).to be_empty
+            weather_agent = scenario_import.scenario.agents.find_by(:guid => "a-weather-agent")
+            trigger_agent = scenario_import.scenario.agents.find_by(:guid => "a-trigger-agent")
+
+            expect(weather_agent.keep_events_for).to eq(2.days)
+            expect(trigger_agent.keep_events_for).to eq(0)
+          end
+        end
+
         describe "with control links" do
           it 'creates the links' do
             valid_parsed_data[:control_links] = [
@@ -342,7 +360,7 @@ describe ScenarioImport do
 
           expect(weather_agent.name).to eq("a weather agent")
           expect(weather_agent.schedule).to eq("5pm")
-          expect(weather_agent.keep_events_for).to eq(14)
+          expect(weather_agent.keep_events_for).to eq(14.days)
           expect(weather_agent.propagate_immediately).to be_falsey
           expect(weather_agent).to be_disabled
           expect(weather_agent.memory).to be_empty
@@ -363,7 +381,7 @@ describe ScenarioImport do
             "0" => {
               "name" => "updated name",
               "schedule" => "6pm",
-              "keep_events_for" => "2",
+              "keep_events_for" => 2.days.to_i.to_s,
               "disabled" => "false",
               "options" => weather_agent_options.merge("api_key" => "foo").to_json
             }
@@ -376,7 +394,7 @@ describe ScenarioImport do
           weather_agent = existing_scenario.agents.find_by(:guid => "a-weather-agent")
           expect(weather_agent.name).to eq("updated name")
           expect(weather_agent.schedule).to eq("6pm")
-          expect(weather_agent.keep_events_for).to eq(2)
+          expect(weather_agent.keep_events_for).to eq(2.days.to_i)
           expect(weather_agent).not_to be_disabled
           expect(weather_agent.options).to eq(weather_agent_options.merge("api_key" => "foo"))
         end
@@ -386,7 +404,7 @@ describe ScenarioImport do
             "0" => {
               "name" => "",
               "schedule" => "foo",
-              "keep_events_for" => "2",
+              "keep_events_for" => 2.days.to_i.to_s,
               "options" => weather_agent_options.merge("api_key" => "").to_json
             }
           }
@@ -419,12 +437,40 @@ describe ScenarioImport do
           end
         end
 
+        context "when the schema_version is less than 1" do
+          it "translates keep_events_for from days to seconds" do
+            valid_parsed_data.delete(:schema_version)
+            valid_parsed_data[:agents] = [valid_parsed_weather_agent_data.merge(keep_events_for: 5)]
+
+            scenario_import.merges = {
+              "0" => {
+                "name" => "a new name",
+                "schedule" => "6pm",
+                "keep_events_for" => 2.days.to_i.to_s,
+                "disabled" => "true",
+                "options" => weather_agent_options.merge("api_key" => "foo").to_json
+              }
+            }
+
+            expect(scenario_import).to be_valid
+
+            weather_agent_diff = scenario_import.agent_diffs[0]
+
+            expect(weather_agent_diff.name.current).to eq(agents(:bob_weather_agent).name)
+            expect(weather_agent_diff.name.incoming).to eq('a weather agent')
+            expect(weather_agent_diff.name.updated).to eq('a new name')
+            expect(weather_agent_diff.keep_events_for.current).to eq(45.days.to_i)
+            expect(weather_agent_diff.keep_events_for.incoming).to eq(5.days.to_i)
+            expect(weather_agent_diff.keep_events_for.updated).to eq(2.days.to_i.to_s)
+          end
+        end
+
         it "sets the 'updated' FieldDiff values based on any feedback from the user" do
           scenario_import.merges = {
             "0" => {
               "name" => "a new name",
               "schedule" => "6pm",
-              "keep_events_for" => "2",
+              "keep_events_for" => 2.days.to_s,
               "disabled" => "true",
               "options" => weather_agent_options.merge("api_key" => "foo").to_json
             },
@@ -444,7 +490,8 @@ describe ScenarioImport do
           expect(weather_agent_diff.name.updated).to eq("a new name")
 
           expect(weather_agent_diff.schedule.updated).to eq("6pm")
-          expect(weather_agent_diff.keep_events_for.updated).to eq("2")
+          expect(weather_agent_diff.keep_events_for.current).to eq(45.days)
+          expect(weather_agent_diff.keep_events_for.updated).to eq(2.days.to_s)
           expect(weather_agent_diff.disabled.updated).to eq("true")
           expect(weather_agent_diff.options.updated).to eq(weather_agent_options.merge("api_key" => "foo"))
         end