@@ -151,6 +151,10 @@ ENABLE_SECOND_PRECISION_SCHEDULE=false  | 
            ||
| 151 | 151 | 
                # at the expense of time accuracy.  | 
            
| 152 | 152 | 
                SCHEDULER_FREQUENCY=0.3  | 
            
| 153 | 153 | 
                 | 
            
| 154 | 
                +# Specify the frequency with which the scheduler checks for event expiration.  | 
            |
| 155 | 
                +# You can use `m` for minutes, `h` for hours, and `d` for days.  | 
            |
| 156 | 
                +EVENT_EXPIRATION_CHECK=3h  | 
            |
| 157 | 
                +  | 
            |
| 154 | 158 | 
                # Use Graphviz for generating diagrams instead of using Google Chart  | 
            
| 155 | 159 | 
                # Tools. Specify a dot(1) command path built with SVG support  | 
            
| 156 | 160 | 
                # enabled.  | 
            
                @@ -21,7 +21,7 @@ class Agent < ActiveRecord::Base  | 
            ||
| 21 | 21 | 
                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  | 
            
| 22 | 22 | 
                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]  | 
            
| 23 | 23 | 
                 | 
            
| 24 | 
                -  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] })]
               | 
            |
| 24 | 
                +  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] })]
               | 
            |
| 25 | 25 | 
                 | 
            
| 26 | 26 | 
                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  | 
            
| 27 | 27 | 
                 | 
            
                @@ -130,14 +130,14 @@ class Agent < ActiveRecord::Base  | 
            ||
| 130 | 130 | 
                end  | 
            
| 131 | 131 | 
                 | 
            
| 132 | 132 | 
                def new_event_expiration_date  | 
            
| 133 | 
                - keep_events_for > 0 ? keep_events_for.days.from_now : nil  | 
            |
| 133 | 
                + keep_events_for > 0 ? keep_events_for.seconds.from_now : nil  | 
            |
| 134 | 134 | 
                end  | 
            
| 135 | 135 | 
                 | 
            
| 136 | 136 | 
                def update_event_expirations!  | 
            
| 137 | 137 | 
                if keep_events_for == 0  | 
            
| 138 | 138 | 
                events.update_all :expires_at => nil  | 
            
| 139 | 139 | 
                else  | 
            
| 140 | 
                -      events.update_all "expires_at = " + rdbms_date_add("created_at", "DAY", keep_events_for.to_i)
               | 
            |
| 140 | 
                +      events.update_all "expires_at = " + rdbms_date_add("created_at", "SECOND", keep_events_for.to_i)
               | 
            |
| 141 | 141 | 
                end  | 
            
| 142 | 142 | 
                end  | 
            
| 143 | 143 | 
                 | 
            
                @@ -142,7 +142,7 @@ class ScenarioImport  | 
            ||
| 142 | 142 | 
                def generate_diff  | 
            
| 143 | 143 | 
                @agent_diffs = (parsed_data['agents'] || []).map.with_index do |agent_data, index|  | 
            
| 144 | 144 | 
                # AgentDiff is defined at the end of this file.  | 
            
| 145 | 
                - agent_diff = AgentDiff.new(agent_data)  | 
            |
| 145 | 
                + agent_diff = AgentDiff.new(agent_data, parsed_data['schema_version'])  | 
            |
| 146 | 146 | 
                if existing_scenario  | 
            
| 147 | 147 | 
                # If this Agent exists already, update the AgentDiff with the local version's information.  | 
            
| 148 | 148 | 
                agent_diff.diff_with! existing_scenario.agents.find_by(:guid => agent_data['guid'])  | 
            
                @@ -184,14 +184,16 @@ class ScenarioImport  | 
            ||
| 184 | 184 | 
                end  | 
            
| 185 | 185 | 
                end  | 
            
| 186 | 186 | 
                 | 
            
| 187 | 
                - def initialize(agent_data)  | 
            |
| 187 | 
                + def initialize(agent_data, schema_version)  | 
            |
| 188 | 188 | 
                super()  | 
            
| 189 | 
                + @schema_version = schema_version  | 
            |
| 189 | 190 | 
                @requires_merge = false  | 
            
| 190 | 191 | 
                self.agent = nil  | 
            
| 191 | 192 | 
                store! agent_data  | 
            
| 192 | 193 | 
                end  | 
            
| 193 | 194 | 
                 | 
            
| 194 | 195 | 
                BASE_FIELDS = %w[name schedule keep_events_for propagate_immediately disabled guid]  | 
            
| 196 | 
                + FIELDS_REQUIRING_TRANSLATION = %w[keep_events_for]  | 
            |
| 195 | 197 | 
                 | 
            
| 196 | 198 | 
                def agent_exists?  | 
            
| 197 | 199 | 
                !!agent  | 
            
                @@ -209,10 +211,27 @@ class ScenarioImport  | 
            ||
| 209 | 211 | 
                       self.type = FieldDiff.new(agent_data["type"].split("::").pop)
               | 
            
| 210 | 212 | 
                       self.options = FieldDiff.new(agent_data['options'] || {})
               | 
            
| 211 | 213 | 
                BASE_FIELDS.each do |option|  | 
            
| 212 | 
                - self[option] = FieldDiff.new(agent_data[option]) if agent_data.has_key?(option)  | 
            |
| 214 | 
                + if agent_data.has_key?(option)  | 
            |
| 215 | 
                + value = agent_data[option]  | 
            |
| 216 | 
                +          value = send(:"translate_#{option}", value) if option.in?(FIELDS_REQUIRING_TRANSLATION)
               | 
            |
| 217 | 
                + self[option] = FieldDiff.new(value)  | 
            |
| 218 | 
                + end  | 
            |
| 219 | 
                + end  | 
            |
| 220 | 
                + end  | 
            |
| 221 | 
                +  | 
            |
| 222 | 
                + def translate_keep_events_for(old_value)  | 
            |
| 223 | 
                + if schema_version < 1  | 
            |
| 224 | 
                + # Was stored in days, now is stored in seconds.  | 
            |
| 225 | 
                + old_value.to_i.days  | 
            |
| 226 | 
                + else  | 
            |
| 227 | 
                + old_value  | 
            |
| 213 | 228 | 
                end  | 
            
| 214 | 229 | 
                end  | 
            
| 215 | 230 | 
                 | 
            
| 231 | 
                + def schema_version  | 
            |
| 232 | 
                + (@schema_version || 0).to_i  | 
            |
| 233 | 
                + end  | 
            |
| 234 | 
                +  | 
            |
| 216 | 235 | 
                def diff_with!(agent)  | 
            
| 217 | 236 | 
                return unless agent.present?  | 
            
| 218 | 237 | 
                 | 
            
                @@ -0,0 +1,13 @@  | 
            ||
| 1 | 
                +class UpdateKeepEventsForToBeInSeconds < ActiveRecord::Migration  | 
            |
| 2 | 
                + class Agent < ActiveRecord::Base; end  | 
            |
| 3 | 
                +  | 
            |
| 4 | 
                + SECONDS_IN_DAY = 60 * 60 * 24  | 
            |
| 5 | 
                +  | 
            |
| 6 | 
                + def up  | 
            |
| 7 | 
                + Agent.update_all ['keep_events_for = keep_events_for * ?', SECONDS_IN_DAY]  | 
            |
| 8 | 
                + end  | 
            |
| 9 | 
                +  | 
            |
| 10 | 
                + def down  | 
            |
| 11 | 
                + Agent.update_all ['keep_events_for = keep_events_for / ?', SECONDS_IN_DAY]  | 
            |
| 12 | 
                + end  | 
            |
| 13 | 
                +end  | 
            
                @@ -11,39 +11,39 @@  | 
            ||
| 11 | 11 | 
                #  | 
            
| 12 | 12 | 
                # It's strongly recommended that you check this file into your version control system.  | 
            
| 13 | 13 | 
                 | 
            
| 14 | 
                -ActiveRecord::Schema.define(version: 20140906030139) do  | 
            |
| 15 | 
                -  | 
            |
| 16 | 
                - create_table "agent_logs", force: true do |t|  | 
            |
| 17 | 
                - t.integer "agent_id", null: false  | 
            |
| 18 | 
                - t.text "message", null: false, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 19 | 
                - t.integer "level", default: 3, null: false  | 
            |
| 20 | 
                - t.integer "inbound_event_id"  | 
            |
| 21 | 
                - t.integer "outbound_event_id"  | 
            |
| 22 | 
                - t.datetime "created_at"  | 
            |
| 23 | 
                - t.datetime "updated_at"  | 
            |
| 14 | 
                +ActiveRecord::Schema.define(version: 20150507153436) do  | 
            |
| 15 | 
                +  | 
            |
| 16 | 
                + create_table "agent_logs", force: :cascade do |t|  | 
            |
| 17 | 
                + t.integer "agent_id", limit: 4, null: false  | 
            |
| 18 | 
                + t.text "message", limit: 16777215, null: false, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 19 | 
                + t.integer "level", limit: 4, default: 3, null: false  | 
            |
| 20 | 
                + t.integer "inbound_event_id", limit: 4  | 
            |
| 21 | 
                + t.integer "outbound_event_id", limit: 4  | 
            |
| 22 | 
                + t.datetime "created_at", null: false  | 
            |
| 23 | 
                + t.datetime "updated_at", null: false  | 
            |
| 24 | 24 | 
                end  | 
            
| 25 | 25 | 
                 | 
            
| 26 | 
                - create_table "agents", force: true do |t|  | 
            |
| 27 | 
                - t.integer "user_id"  | 
            |
| 28 | 
                - t.text "options", charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 29 | 
                - t.string "type", collation: "utf8_bin"  | 
            |
| 30 | 
                - t.string "name", charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 31 | 
                - t.string "schedule", collation: "utf8_bin"  | 
            |
| 32 | 
                - t.integer "events_count", default: 0, null: false  | 
            |
| 26 | 
                + create_table "agents", force: :cascade do |t|  | 
            |
| 27 | 
                + t.integer "user_id", limit: 4  | 
            |
| 28 | 
                + t.text "options", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 29 | 
                + t.string "type", limit: 255, collation: "utf8_bin"  | 
            |
| 30 | 
                + t.string "name", limit: 255, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 31 | 
                + t.string "schedule", limit: 255, collation: "utf8_bin"  | 
            |
| 32 | 
                + t.integer "events_count", limit: 4, default: 0, null: false  | 
            |
| 33 | 33 | 
                t.datetime "last_check_at"  | 
            
| 34 | 34 | 
                t.datetime "last_receive_at"  | 
            
| 35 | 
                - t.integer "last_checked_event_id"  | 
            |
| 36 | 
                - t.datetime "created_at"  | 
            |
| 37 | 
                - t.datetime "updated_at"  | 
            |
| 38 | 
                - t.text "memory", limit: 2147483647, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 35 | 
                + t.integer "last_checked_event_id", limit: 4  | 
            |
| 36 | 
                + t.datetime "created_at", null: false  | 
            |
| 37 | 
                + t.datetime "updated_at", null: false  | 
            |
| 38 | 
                + t.text "memory", limit: 4294967295, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 39 | 39 | 
                t.datetime "last_web_request_at"  | 
            
| 40 | 
                - t.integer "keep_events_for", default: 0, null: false  | 
            |
| 41 | 40 | 
                t.datetime "last_event_at"  | 
            
| 42 | 41 | 
                t.datetime "last_error_log_at"  | 
            
| 43 | 
                - t.boolean "propagate_immediately", default: false, null: false  | 
            |
| 44 | 
                - t.boolean "disabled", default: false, null: false  | 
            |
| 45 | 
                - t.integer "service_id"  | 
            |
| 46 | 
                - t.string "guid", null: false  | 
            |
| 42 | 
                + t.integer "keep_events_for", limit: 4, default: 0, null: false  | 
            |
| 43 | 
                + t.boolean "propagate_immediately", limit: 1, default: false, null: false  | 
            |
| 44 | 
                + t.boolean "disabled", limit: 1, default: false, null: false  | 
            |
| 45 | 
                + t.string "guid", limit: 255, null: false, charset: "ascii", collation: "ascii_bin"  | 
            |
| 46 | 
                + t.integer "service_id", limit: 4  | 
            |
| 47 | 47 | 
                end  | 
            
| 48 | 48 | 
                 | 
            
| 49 | 49 | 
                add_index "agents", ["guid"], name: "index_agents_on_guid", using: :btree  | 
            
                @@ -51,9 +51,17 @@ ActiveRecord::Schema.define(version: 20140906030139) do  | 
            ||
| 51 | 51 | 
                add_index "agents", ["type"], name: "index_agents_on_type", using: :btree  | 
            
| 52 | 52 | 
                add_index "agents", ["user_id", "created_at"], name: "index_agents_on_user_id_and_created_at", using: :btree  | 
            
| 53 | 53 | 
                 | 
            
| 54 | 
                - create_table "control_links", force: true do |t|  | 
            |
| 55 | 
                - t.integer "controller_id", null: false  | 
            |
| 56 | 
                - t.integer "control_target_id", null: false  | 
            |
| 54 | 
                + create_table "contacts", force: :cascade do |t|  | 
            |
| 55 | 
                + t.text "message", limit: 65535, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 56 | 
                + t.string "name", limit: 255, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 57 | 
                + t.string "email", limit: 255, collation: "utf8_bin"  | 
            |
| 58 | 
                + t.datetime "created_at", null: false  | 
            |
| 59 | 
                + t.datetime "updated_at", null: false  | 
            |
| 60 | 
                + end  | 
            |
| 61 | 
                +  | 
            |
| 62 | 
                + create_table "control_links", force: :cascade do |t|  | 
            |
| 63 | 
                + t.integer "controller_id", limit: 4, null: false  | 
            |
| 64 | 
                + t.integer "control_target_id", limit: 4, null: false  | 
            |
| 57 | 65 | 
                t.datetime "created_at"  | 
            
| 58 | 66 | 
                t.datetime "updated_at"  | 
            
| 59 | 67 | 
                end  | 
            
                @@ -61,30 +69,30 @@ ActiveRecord::Schema.define(version: 20140906030139) do  | 
            ||
| 61 | 69 | 
                add_index "control_links", ["control_target_id"], name: "index_control_links_on_control_target_id", using: :btree  | 
            
| 62 | 70 | 
                add_index "control_links", ["controller_id", "control_target_id"], name: "index_control_links_on_controller_id_and_control_target_id", unique: true, using: :btree  | 
            
| 63 | 71 | 
                 | 
            
| 64 | 
                - create_table "delayed_jobs", force: true do |t|  | 
            |
| 65 | 
                - t.integer "priority", default: 0  | 
            |
| 66 | 
                - t.integer "attempts", default: 0  | 
            |
| 67 | 
                - t.text "handler", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 68 | 
                - t.text "last_error", charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 72 | 
                + create_table "delayed_jobs", force: :cascade do |t|  | 
            |
| 73 | 
                + t.integer "priority", limit: 4, default: 0  | 
            |
| 74 | 
                + t.integer "attempts", limit: 4, default: 0  | 
            |
| 75 | 
                + t.text "handler", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 76 | 
                + t.text "last_error", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 69 | 77 | 
                t.datetime "run_at"  | 
            
| 70 | 78 | 
                t.datetime "locked_at"  | 
            
| 71 | 79 | 
                t.datetime "failed_at"  | 
            
| 72 | 
                - t.string "locked_by"  | 
            |
| 73 | 
                - t.string "queue"  | 
            |
| 74 | 
                - t.datetime "created_at"  | 
            |
| 75 | 
                - t.datetime "updated_at"  | 
            |
| 80 | 
                + t.string "locked_by", limit: 255  | 
            |
| 81 | 
                + t.string "queue", limit: 255  | 
            |
| 82 | 
                + t.datetime "created_at", null: false  | 
            |
| 83 | 
                + t.datetime "updated_at", null: false  | 
            |
| 76 | 84 | 
                end  | 
            
| 77 | 85 | 
                 | 
            
| 78 | 86 | 
                add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority", using: :btree  | 
            
| 79 | 87 | 
                 | 
            
| 80 | 
                - create_table "events", force: true do |t|  | 
            |
| 81 | 
                - t.integer "user_id"  | 
            |
| 82 | 
                - t.integer "agent_id"  | 
            |
| 83 | 
                - t.decimal "lat", precision: 15, scale: 10  | 
            |
| 84 | 
                - t.decimal "lng", precision: 15, scale: 10  | 
            |
| 85 | 
                - t.text "payload", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 86 | 
                - t.datetime "created_at"  | 
            |
| 87 | 
                - t.datetime "updated_at"  | 
            |
| 88 | 
                + create_table "events", force: :cascade do |t|  | 
            |
| 89 | 
                + t.integer "user_id", limit: 4  | 
            |
| 90 | 
                + t.integer "agent_id", limit: 4  | 
            |
| 91 | 
                + t.decimal "lat", precision: 15, scale: 10  | 
            |
| 92 | 
                + t.decimal "lng", precision: 15, scale: 10  | 
            |
| 93 | 
                + t.text "payload", limit: 4294967295, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 94 | 
                + t.datetime "created_at", null: false  | 
            |
| 95 | 
                + t.datetime "updated_at", null: false  | 
            |
| 88 | 96 | 
                t.datetime "expires_at"  | 
            
| 89 | 97 | 
                end  | 
            
| 90 | 98 | 
                 | 
            
                @@ -92,20 +100,33 @@ ActiveRecord::Schema.define(version: 20140906030139) do  | 
            ||
| 92 | 100 | 
                add_index "events", ["expires_at"], name: "index_events_on_expires_at", using: :btree  | 
            
| 93 | 101 | 
                add_index "events", ["user_id", "created_at"], name: "index_events_on_user_id_and_created_at", using: :btree  | 
            
| 94 | 102 | 
                 | 
            
| 95 | 
                - create_table "links", force: true do |t|  | 
            |
| 96 | 
                - t.integer "source_id"  | 
            |
| 97 | 
                - t.integer "receiver_id"  | 
            |
| 98 | 
                - t.datetime "created_at"  | 
            |
| 99 | 
                - t.datetime "updated_at"  | 
            |
| 100 | 
                - t.integer "event_id_at_creation", default: 0, null: false  | 
            |
| 103 | 
                + create_table "links", force: :cascade do |t|  | 
            |
| 104 | 
                + t.integer "source_id", limit: 4  | 
            |
| 105 | 
                + t.integer "receiver_id", limit: 4  | 
            |
| 106 | 
                + t.datetime "created_at", null: false  | 
            |
| 107 | 
                + t.datetime "updated_at", null: false  | 
            |
| 108 | 
                + t.integer "event_id_at_creation", limit: 4, default: 0, null: false  | 
            |
| 101 | 109 | 
                end  | 
            
| 102 | 110 | 
                 | 
            
| 103 | 111 | 
                add_index "links", ["receiver_id", "source_id"], name: "index_links_on_receiver_id_and_source_id", using: :btree  | 
            
| 104 | 112 | 
                add_index "links", ["source_id", "receiver_id"], name: "index_links_on_source_id_and_receiver_id", using: :btree  | 
            
| 105 | 113 | 
                 | 
            
| 106 | 
                - create_table "scenario_memberships", force: true do |t|  | 
            |
| 107 | 
                - t.integer "agent_id", null: false  | 
            |
| 108 | 
                - t.integer "scenario_id", null: false  | 
            |
| 114 | 
                + create_table "rails_admin_histories", force: :cascade do |t|  | 
            |
| 115 | 
                + t.text "message", limit: 65535, charset: "latin1", collation: "latin1_swedish_ci"  | 
            |
| 116 | 
                + t.string "username", limit: 255, charset: "latin1", collation: "latin1_swedish_ci"  | 
            |
| 117 | 
                + t.integer "item", limit: 4  | 
            |
| 118 | 
                + t.string "table", limit: 255, charset: "latin1", collation: "latin1_swedish_ci"  | 
            |
| 119 | 
                + t.integer "month", limit: 2  | 
            |
| 120 | 
                + t.integer "year", limit: 8  | 
            |
| 121 | 
                + t.datetime "created_at", null: false  | 
            |
| 122 | 
                + t.datetime "updated_at", null: false  | 
            |
| 123 | 
                + end  | 
            |
| 124 | 
                +  | 
            |
| 125 | 
                + add_index "rails_admin_histories", ["item", "table", "month", "year"], name: "index_rails_admin_histories", using: :btree  | 
            |
| 126 | 
                +  | 
            |
| 127 | 
                + create_table "scenario_memberships", force: :cascade do |t|  | 
            |
| 128 | 
                + t.integer "agent_id", limit: 4, null: false  | 
            |
| 129 | 
                + t.integer "scenario_id", limit: 4, null: false  | 
            |
| 109 | 130 | 
                t.datetime "created_at"  | 
            
| 110 | 131 | 
                t.datetime "updated_at"  | 
            
| 111 | 132 | 
                end  | 
            
                @@ -113,71 +134,88 @@ ActiveRecord::Schema.define(version: 20140906030139) do  | 
            ||
| 113 | 134 | 
                add_index "scenario_memberships", ["agent_id"], name: "index_scenario_memberships_on_agent_id", using: :btree  | 
            
| 114 | 135 | 
                add_index "scenario_memberships", ["scenario_id"], name: "index_scenario_memberships_on_scenario_id", using: :btree  | 
            
| 115 | 136 | 
                 | 
            
| 116 | 
                - create_table "scenarios", force: true do |t|  | 
            |
| 117 | 
                - t.string "name", null: false, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 118 | 
                - t.integer "user_id", null: false  | 
            |
| 137 | 
                + create_table "scenarios", force: :cascade do |t|  | 
            |
| 138 | 
                + t.string "name", limit: 255, null: false, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 139 | 
                + t.integer "user_id", limit: 4, null: false  | 
            |
| 119 | 140 | 
                t.datetime "created_at"  | 
            
| 120 | 141 | 
                t.datetime "updated_at"  | 
            
| 121 | 
                - t.text "description", charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 122 | 
                - t.boolean "public", default: false, null: false  | 
            |
| 123 | 
                - t.string "guid", null: false, charset: "ascii", collation: "ascii_bin"  | 
            |
| 124 | 
                - t.string "source_url"  | 
            |
| 125 | 
                - t.string "tag_bg_color"  | 
            |
| 126 | 
                - t.string "tag_fg_color"  | 
            |
| 142 | 
                + t.text "description", limit: 65535, charset: "utf8mb4", collation: "utf8mb4_bin"  | 
            |
| 143 | 
                + t.boolean "public", limit: 1, default: false, null: false  | 
            |
| 144 | 
                + t.string "guid", limit: 255, null: false, charset: "ascii", collation: "ascii_bin"  | 
            |
| 145 | 
                + t.string "source_url", limit: 255  | 
            |
| 146 | 
                + t.string "tag_bg_color", limit: 255  | 
            |
| 147 | 
                + t.string "tag_fg_color", limit: 255  | 
            |
| 127 | 148 | 
                end  | 
            
| 128 | 149 | 
                 | 
            
| 129 | 150 | 
                add_index "scenarios", ["user_id", "guid"], name: "index_scenarios_on_user_id_and_guid", unique: true, using: :btree  | 
            
| 130 | 151 | 
                 | 
            
| 131 | 
                - create_table "services", force: true do |t|  | 
            |
| 132 | 
                - t.integer "user_id", null: false  | 
            |
| 133 | 
                - t.string "provider", null: false  | 
            |
| 134 | 
                - t.string "name", null: false  | 
            |
| 135 | 
                - t.text "token", null: false  | 
            |
| 136 | 
                - t.text "secret"  | 
            |
| 137 | 
                - t.text "refresh_token"  | 
            |
| 152 | 
                + create_table "services", force: :cascade do |t|  | 
            |
| 153 | 
                + t.integer "user_id", limit: 4, null: false  | 
            |
| 154 | 
                + t.string "provider", limit: 255, null: false, charset: "latin1", collation: "latin1_swedish_ci"  | 
            |
| 155 | 
                + t.string "name", limit: 255, null: false, charset: "latin1", collation: "latin1_swedish_ci"  | 
            |
| 156 | 
                + t.text "token", limit: 65535, null: false, charset: "latin1", collation: "latin1_swedish_ci"  | 
            |
| 157 | 
                + t.text "secret", limit: 65535, charset: "latin1", collation: "latin1_swedish_ci"  | 
            |
| 158 | 
                + t.text "refresh_token", limit: 65535, charset: "latin1", collation: "latin1_swedish_ci"  | 
            |
| 138 | 159 | 
                t.datetime "expires_at"  | 
            
| 139 | 
                - t.boolean "global", default: false  | 
            |
| 140 | 
                - t.text "options"  | 
            |
| 160 | 
                + t.boolean "global", limit: 1, default: false  | 
            |
| 161 | 
                + t.text "options", limit: 65535, charset: "latin1", collation: "latin1_swedish_ci"  | 
            |
| 141 | 162 | 
                t.datetime "created_at"  | 
            
| 142 | 163 | 
                t.datetime "updated_at"  | 
            
| 143 | 
                - t.string "uid"  | 
            |
| 164 | 
                + t.string "uid", limit: 255, charset: "latin1", collation: "latin1_swedish_ci"  | 
            |
| 144 | 165 | 
                end  | 
            
| 145 | 166 | 
                 | 
            
| 146 | 167 | 
                add_index "services", ["provider"], name: "index_services_on_provider", using: :btree  | 
            
| 147 | 168 | 
                add_index "services", ["uid"], name: "index_services_on_uid", using: :btree  | 
            
| 148 | 169 | 
                add_index "services", ["user_id", "global"], name: "index_services_on_user_id_and_global", using: :btree  | 
            
| 149 | 170 | 
                 | 
            
| 150 | 
                - create_table "user_credentials", force: true do |t|  | 
            |
| 151 | 
                - t.integer "user_id", null: false  | 
            |
| 152 | 
                - t.string "credential_name", null: false  | 
            |
| 153 | 
                - t.text "credential_value", null: false  | 
            |
| 171 | 
                + create_table "taggings", force: :cascade do |t|  | 
            |
| 172 | 
                + t.integer "tag_id", limit: 4  | 
            |
| 173 | 
                + t.integer "taggable_id", limit: 4  | 
            |
| 174 | 
                + t.string "taggable_type", limit: 255, collation: "utf8_general_ci"  | 
            |
| 175 | 
                + t.integer "tagger_id", limit: 4  | 
            |
| 176 | 
                + t.string "tagger_type", limit: 255, collation: "utf8_general_ci"  | 
            |
| 177 | 
                + t.string "context", limit: 128, collation: "utf8_general_ci"  | 
            |
| 154 | 178 | 
                t.datetime "created_at"  | 
            
| 155 | 
                - t.datetime "updated_at"  | 
            |
| 156 | 
                - t.string "mode", default: "text", null: false, collation: "utf8_bin"  | 
            |
| 179 | 
                + end  | 
            |
| 180 | 
                +  | 
            |
| 181 | 
                + add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id", using: :btree  | 
            |
| 182 | 
                + add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree  | 
            |
| 183 | 
                +  | 
            |
| 184 | 
                + create_table "tags", force: :cascade do |t|  | 
            |
| 185 | 
                + t.string "name", limit: 255, collation: "utf8_general_ci"  | 
            |
| 186 | 
                + end  | 
            |
| 187 | 
                +  | 
            |
| 188 | 
                + create_table "user_credentials", force: :cascade do |t|  | 
            |
| 189 | 
                + t.integer "user_id", limit: 4, null: false  | 
            |
| 190 | 
                + t.string "credential_name", limit: 255, null: false  | 
            |
| 191 | 
                + t.text "credential_value", limit: 65535, null: false  | 
            |
| 192 | 
                + t.datetime "created_at", null: false  | 
            |
| 193 | 
                + t.datetime "updated_at", null: false  | 
            |
| 194 | 
                + t.string "mode", limit: 255, default: "text", null: false, collation: "utf8_bin"  | 
            |
| 157 | 195 | 
                end  | 
            
| 158 | 196 | 
                 | 
            
| 159 | 197 | 
                add_index "user_credentials", ["user_id", "credential_name"], name: "index_user_credentials_on_user_id_and_credential_name", unique: true, using: :btree  | 
            
| 160 | 198 | 
                 | 
            
| 161 | 
                - create_table "users", force: true do |t|  | 
            |
| 162 | 
                - t.string "email", default: "", null: false, collation: "utf8_bin"  | 
            |
| 163 | 
                - t.string "encrypted_password", default: "", null: false, charset: "ascii", collation: "ascii_bin"  | 
            |
| 164 | 
                - t.string "reset_password_token", collation: "utf8_bin"  | 
            |
| 199 | 
                + create_table "users", force: :cascade do |t|  | 
            |
| 200 | 
                + t.string "email", limit: 255, default: "", null: false, collation: "utf8_bin"  | 
            |
| 201 | 
                + t.string "encrypted_password", limit: 255, default: "", null: false, charset: "ascii", collation: "ascii_bin"  | 
            |
| 202 | 
                + t.string "reset_password_token", limit: 255, collation: "utf8_bin"  | 
            |
| 165 | 203 | 
                t.datetime "reset_password_sent_at"  | 
            
| 166 | 204 | 
                t.datetime "remember_created_at"  | 
            
| 167 | 
                - t.integer "sign_in_count", default: 0  | 
            |
| 205 | 
                + t.integer "sign_in_count", limit: 4, default: 0  | 
            |
| 168 | 206 | 
                t.datetime "current_sign_in_at"  | 
            
| 169 | 207 | 
                t.datetime "last_sign_in_at"  | 
            
| 170 | 
                - t.string "current_sign_in_ip"  | 
            |
| 171 | 
                - t.string "last_sign_in_ip"  | 
            |
| 172 | 
                - t.datetime "created_at"  | 
            |
| 173 | 
                - t.datetime "updated_at"  | 
            |
| 174 | 
                - t.boolean "admin", default: false, null: false  | 
            |
| 175 | 
                - t.integer "failed_attempts", default: 0  | 
            |
| 176 | 
                - t.string "unlock_token"  | 
            |
| 208 | 
                + t.string "current_sign_in_ip", limit: 255  | 
            |
| 209 | 
                + t.string "last_sign_in_ip", limit: 255  | 
            |
| 210 | 
                + t.datetime "created_at", null: false  | 
            |
| 211 | 
                + t.datetime "updated_at", null: false  | 
            |
| 212 | 
                + t.boolean "admin", limit: 1, default: false, null: false  | 
            |
| 213 | 
                + t.integer "failed_attempts", limit: 4, default: 0  | 
            |
| 214 | 
                + t.string "unlock_token", limit: 255  | 
            |
| 177 | 215 | 
                t.datetime "locked_at"  | 
            
| 178 | 216 | 
                t.string "username", limit: 191, null: false, charset: "utf8mb4", collation: "utf8mb4_unicode_ci"  | 
            
| 179 | 
                - t.string "invitation_code", null: false, collation: "utf8_bin"  | 
            |
| 180 | 
                - t.integer "scenario_count", default: 0, null: false  | 
            |
| 217 | 
                + t.string "invitation_code", limit: 255, null: false, collation: "utf8_bin"  | 
            |
| 218 | 
                + t.integer "scenario_count", limit: 4, default: 0, null: false  | 
            |
| 181 | 219 | 
                end  | 
            
| 182 | 220 | 
                 | 
            
| 183 | 221 | 
                add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree  | 
            
                @@ -12,6 +12,7 @@ class AgentsExporter  | 
            ||
| 12 | 12 | 
                 | 
            
| 13 | 13 | 
                   def as_json(opts = {})
               | 
            
| 14 | 14 | 
                     {
               | 
            
| 15 | 
                + :schema_version => 1,  | 
            |
| 15 | 16 | 
                :name => options[:name].presence || 'No name provided',  | 
            
| 16 | 17 | 
                :description => options[:description].presence || 'No description provided',  | 
            
| 17 | 18 | 
                :source_url => options[:source_url],  | 
            
                @@ -114,7 +114,7 @@ class HuginnScheduler  | 
            ||
| 114 | 114 | 
                end  | 
            
| 115 | 115 | 
                 | 
            
| 116 | 116 | 
                # Schedule event cleanup.  | 
            
| 117 | 
                - @rufus_scheduler.cron "0 0 * * * " + tzinfo_friendly_timezone do  | 
            |
| 117 | 
                + @rufus_scheduler.every ENV['EVENT_EXPIRATION_CHECK'].presence || '6h' do  | 
            |
| 118 | 118 | 
                cleanup_expired_events!  | 
            
| 119 | 119 | 
                end  | 
            
| 120 | 120 | 
                 | 
            
                @@ -38,7 +38,7 @@ bob_weather_agent:  | 
            ||
| 38 | 38 | 
                schedule: "midnight"  | 
            
| 39 | 39 | 
                name: "SF Weather"  | 
            
| 40 | 40 | 
                guid: <%= SecureRandom.hex %>  | 
            
| 41 | 
                - keep_events_for: 45  | 
            |
| 41 | 
                + keep_events_for: <%= 45.days %>  | 
            |
| 42 | 42 | 
                   options: <%= { :location => 94102, :lat => 37.779329, :lng => -122.41915, :api_key => 'test' }.to_json.inspect %>
               | 
            
| 43 | 43 | 
                 | 
            
| 44 | 44 | 
                jane_weather_agent:  | 
            
                @@ -47,7 +47,7 @@ jane_weather_agent:  | 
            ||
| 47 | 47 | 
                schedule: "midnight"  | 
            
| 48 | 48 | 
                name: "SF Weather"  | 
            
| 49 | 49 | 
                guid: <%= SecureRandom.hex %>  | 
            
| 50 | 
                - keep_events_for: 30  | 
            |
| 50 | 
                + keep_events_for: <%= 30.days %>  | 
            |
| 51 | 51 | 
                   options: <%= { :location => 94103, :lat => 37.779329, :lng => -122.41915, :api_key => 'test' }.to_json.inspect %>
               | 
            
| 52 | 52 | 
                 | 
            
| 53 | 53 | 
                jane_rain_notifier_agent:  | 
            
                @@ -21,6 +21,7 @@ describe AgentsExporter do  | 
            ||
| 21 | 21 | 
                expect(data[:description]).to eq(description)  | 
            
| 22 | 22 | 
                expect(data[:source_url]).to eq(source_url)  | 
            
| 23 | 23 | 
                expect(data[:guid]).to eq(guid)  | 
            
| 24 | 
                + expect(data[:schema_version]).to eq(1)  | 
            |
| 24 | 25 | 
                expect(data[:tag_fg_color]).to eq(tag_fg_color)  | 
            
| 25 | 26 | 
                expect(data[:tag_bg_color]).to eq(tag_bg_color)  | 
            
| 26 | 27 | 
                expect(Time.parse(data[:exported_at])).to be_within(2).of(Time.now.utc)  | 
            
                @@ -546,11 +546,11 @@ describe Agent do  | 
            ||
| 546 | 546 | 
                expect(agent).to have(1).errors_on(:keep_events_for)  | 
            
| 547 | 547 | 
                agent.keep_events_for = ""  | 
            
| 548 | 548 | 
                expect(agent).to have(1).errors_on(:keep_events_for)  | 
            
| 549 | 
                - agent.keep_events_for = 5  | 
            |
| 549 | 
                + agent.keep_events_for = 5.days.to_i  | 
            |
| 550 | 550 | 
                expect(agent).to be_valid  | 
            
| 551 | 551 | 
                agent.keep_events_for = 0  | 
            
| 552 | 552 | 
                expect(agent).to be_valid  | 
            
| 553 | 
                - agent.keep_events_for = 365  | 
            |
| 553 | 
                + agent.keep_events_for = 365.days.to_i  | 
            |
| 554 | 554 | 
                expect(agent).to be_valid  | 
            
| 555 | 555 | 
                 | 
            
| 556 | 556 | 
                # Rails seems to call to_i on the input. This guards against future changes to that behavior.  | 
            
                @@ -564,7 +564,7 @@ describe Agent do  | 
            ||
| 564 | 564 | 
                @time = "2014-01-01 01:00:00 +00:00"  | 
            
| 565 | 565 | 
                time_travel_to @time do  | 
            
| 566 | 566 | 
                @agent = Agents::SomethingSource.new(:name => "something")  | 
            
| 567 | 
                - @agent.keep_events_for = 5  | 
            |
| 567 | 
                + @agent.keep_events_for = 5.days  | 
            |
| 568 | 568 | 
                @agent.user = users(:bob)  | 
            
| 569 | 569 | 
                @agent.save!  | 
            
| 570 | 570 | 
                           @event = @agent.create_event :payload => { "hello" => "world" }
               | 
            
                @@ -580,7 +580,7 @@ describe Agent do  | 
            ||
| 580 | 580 | 
                @agent.save!  | 
            
| 581 | 581 | 
                 | 
            
| 582 | 582 | 
                @agent.options[:foo] = "bar1"  | 
            
| 583 | 
                - @agent.keep_events_for = 5  | 
            |
| 583 | 
                + @agent.keep_events_for = 5.days  | 
            |
| 584 | 584 | 
                @agent.save!  | 
            
| 585 | 585 | 
                end  | 
            
| 586 | 586 | 
                end  | 
            
                @@ -590,7 +590,7 @@ describe Agent do  | 
            ||
| 590 | 590 | 
                time_travel_to @time do  | 
            
| 591 | 591 | 
                             expect {
               | 
            
| 592 | 592 | 
                @agent.options[:foo] = "bar1"  | 
            
| 593 | 
                - @agent.keep_events_for = 3  | 
            |
| 593 | 
                + @agent.keep_events_for = 3.days  | 
            |
| 594 | 594 | 
                @agent.save!  | 
            
| 595 | 595 | 
                             }.to change { @event.reload.expires_at }
               | 
            
| 596 | 596 | 
                expect(@event.expires_at.to_i).to be_within(2).of(3.days.from_now.to_i)  | 
            
                @@ -603,7 +603,7 @@ describe Agent do  | 
            ||
| 603 | 603 | 
                 | 
            
| 604 | 604 | 
                           expect {
               | 
            
| 605 | 605 | 
                @agent.options[:foo] = "bar2"  | 
            
| 606 | 
                - @agent.keep_events_for = 3  | 
            |
| 606 | 
                + @agent.keep_events_for = 3.days  | 
            |
| 607 | 607 | 
                @agent.save!  | 
            
| 608 | 608 | 
                           }.to change { @event.reload.expires_at }
               | 
            
| 609 | 609 | 
                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  | 
            ||
| 635 | 635 | 
                @receiver = Agents::CannotBeScheduled.new(  | 
            
| 636 | 636 | 
                name: 'Agent',  | 
            
| 637 | 637 | 
                           options: { foo: 'bar3' },
               | 
            
| 638 | 
                - keep_events_for: 3,  | 
            |
| 638 | 
                + keep_events_for: 3.days,  | 
            |
| 639 | 639 | 
                propagate_immediately: true)  | 
            
| 640 | 640 | 
                @receiver.user = users(:bob)  | 
            
| 641 | 641 | 
                @receiver.sources << @sender  | 
            
                @@ -747,7 +747,7 @@ describe Agent do  | 
            ||
| 747 | 747 | 
                 | 
            
| 748 | 748 | 
                it "sets expires_at on created events" do  | 
            
| 749 | 749 | 
                         event = agents(:jane_weather_agent).create_event :payload => { 'hi' => 'there' }
               | 
            
| 750 | 
                - expect(event.expires_at.to_i).to be_within(5).of(agents(:jane_weather_agent).keep_events_for.days.from_now.to_i)  | 
            |
| 750 | 
                + expect(event.expires_at.to_i).to be_within(5).of(agents(:jane_weather_agent).keep_events_for.seconds.from_now.to_i)  | 
            |
| 751 | 751 | 
                end  | 
            
| 752 | 752 | 
                end  | 
            
| 753 | 753 | 
                 | 
            
                @@ -836,7 +836,7 @@ describe AgentDrop do  | 
            ||
| 836 | 836 | 
                },  | 
            
| 837 | 837 | 
                },  | 
            
| 838 | 838 | 
                schedule: 'every_1h',  | 
            
| 839 | 
                - keep_events_for: 2)  | 
            |
| 839 | 
                + keep_events_for: 2.days)  | 
            |
| 840 | 840 | 
                @wsa1.user = users(:bob)  | 
            
| 841 | 841 | 
                @wsa1.save!  | 
            
| 842 | 842 | 
                 | 
            
                @@ -853,7 +853,7 @@ describe AgentDrop do  | 
            ||
| 853 | 853 | 
                },  | 
            
| 854 | 854 | 
                },  | 
            
| 855 | 855 | 
                schedule: 'every_12h',  | 
            
| 856 | 
                - keep_events_for: 2)  | 
            |
| 856 | 
                + keep_events_for: 2.days)  | 
            |
| 857 | 857 | 
                @wsa2.user = users(:bob)  | 
            
| 858 | 858 | 
                @wsa2.save!  | 
            
| 859 | 859 | 
                 | 
            
                @@ -868,7 +868,7 @@ describe AgentDrop do  | 
            ||
| 868 | 868 | 
                matchers: [],  | 
            
| 869 | 869 | 
                skip_created_at: 'false',  | 
            
| 870 | 870 | 
                },  | 
            
| 871 | 
                - keep_events_for: 2,  | 
            |
| 871 | 
                + keep_events_for: 2.days,  | 
            |
| 872 | 872 | 
                propagate_immediately: true)  | 
            
| 873 | 873 | 
                @efa.user = users(:bob)  | 
            
| 874 | 874 | 
                @efa.sources << @wsa1 << @wsa2  | 
            
                @@ -9,7 +9,7 @@ describe Agents::FtpsiteAgent do  | 
            ||
| 9 | 9 | 
                'url' => "ftp://ftp.example.org/pub/releases/",  | 
            
| 10 | 10 | 
                'patterns' => ["example*.tar.gz"],  | 
            
| 11 | 11 | 
                }  | 
            
| 12 | 
                - @checker = Agents::FtpsiteAgent.new(:name => "Example", :options => @site, :keep_events_for => 2)  | 
            |
| 12 | 
                + @checker = Agents::FtpsiteAgent.new(:name => "Example", :options => @site, :keep_events_for => 2.days)  | 
            |
| 13 | 13 | 
                @checker.user = users(:bob)  | 
            
| 14 | 14 | 
                @checker.save!  | 
            
| 15 | 15 | 
                end  | 
            
                @@ -14,7 +14,7 @@ describe Agents::ImapFolderAgent do  | 
            ||
| 14 | 14 | 
                         'conditions' => {
               | 
            
| 15 | 15 | 
                }  | 
            
| 16 | 16 | 
                }  | 
            
| 17 | 
                - @checker = Agents::ImapFolderAgent.new(:name => 'Example', :options => @site, :keep_events_for => 2)  | 
            |
| 17 | 
                + @checker = Agents::ImapFolderAgent.new(:name => 'Example', :options => @site, :keep_events_for => 2.days)  | 
            |
| 18 | 18 | 
                @checker.user = users(:bob)  | 
            
| 19 | 19 | 
                @checker.save!  | 
            
| 20 | 20 | 
                 | 
            
                @@ -20,7 +20,7 @@ describe Agents::WebsiteAgent do  | 
            ||
| 20 | 20 | 
                           'hovertext' => { 'css' => "#comic img", 'value' => "@title" }
               | 
            
| 21 | 21 | 
                }  | 
            
| 22 | 22 | 
                }  | 
            
| 23 | 
                - @checker = Agents::WebsiteAgent.new(:name => "xkcd", :options => @valid_options, :keep_events_for => 2)  | 
            |
| 23 | 
                + @checker = Agents::WebsiteAgent.new(:name => "xkcd", :options => @valid_options, :keep_events_for => 2.days)  | 
            |
| 24 | 24 | 
                @checker.user = users(:bob)  | 
            
| 25 | 25 | 
                @checker.save!  | 
            
| 26 | 26 | 
                end  | 
            
                @@ -30,7 +30,7 @@ describe ScenarioImport do  | 
            ||
| 30 | 30 | 
                :type => "Agents::WeatherAgent",  | 
            
| 31 | 31 | 
                :name => "a weather agent",  | 
            
| 32 | 32 | 
                :schedule => "5pm",  | 
            
| 33 | 
                - :keep_events_for => 14,  | 
            |
| 33 | 
                + :keep_events_for => 14.days,  | 
            |
| 34 | 34 | 
                :disabled => true,  | 
            
| 35 | 35 | 
                :guid => "a-weather-agent",  | 
            
| 36 | 36 | 
                :options => weather_agent_options  | 
            
                @@ -61,6 +61,7 @@ describe ScenarioImport do  | 
            ||
| 61 | 61 | 
                end  | 
            
| 62 | 62 | 
                let(:valid_parsed_data) do  | 
            
| 63 | 63 | 
                     {
               | 
            
| 64 | 
                + :schema_version => 1,  | 
            |
| 64 | 65 | 
                :name => name,  | 
            
| 65 | 66 | 
                :description => description,  | 
            
| 66 | 67 | 
                :guid => guid,  | 
            
                @@ -203,7 +204,7 @@ describe ScenarioImport do  | 
            ||
| 203 | 204 | 
                 | 
            
| 204 | 205 | 
                           expect(weather_agent.name).to eq("a weather agent")
               | 
            
| 205 | 206 | 
                           expect(weather_agent.schedule).to eq("5pm")
               | 
            
| 206 | 
                - expect(weather_agent.keep_events_for).to eq(14)  | 
            |
| 207 | 
                + expect(weather_agent.keep_events_for).to eq(14.days)  | 
            |
| 207 | 208 | 
                expect(weather_agent.propagate_immediately).to be_falsey  | 
            
| 208 | 209 | 
                expect(weather_agent).to be_disabled  | 
            
| 209 | 210 | 
                expect(weather_agent.memory).to be_empty  | 
            
                @@ -226,6 +227,23 @@ describe ScenarioImport do  | 
            ||
| 226 | 227 | 
                scenario_import.import  | 
            
| 227 | 228 | 
                           }.to change { users(:bob).agents.count }.by(2)
               | 
            
| 228 | 229 | 
                end  | 
            
| 230 | 
                +  | 
            |
| 231 | 
                + context "when the schema_version is less than 1" do  | 
            |
| 232 | 
                + before do  | 
            |
| 233 | 
                + valid_parsed_weather_agent_data[:keep_events_for] = 2  | 
            |
| 234 | 
                + valid_parsed_data.delete(:schema_version)  | 
            |
| 235 | 
                + end  | 
            |
| 236 | 
                +  | 
            |
| 237 | 
                + it "translates keep_events_for from days to seconds" do  | 
            |
| 238 | 
                + scenario_import.import  | 
            |
| 239 | 
                + expect(scenario_import.errors).to be_empty  | 
            |
| 240 | 
                + weather_agent = scenario_import.scenario.agents.find_by(:guid => "a-weather-agent")  | 
            |
| 241 | 
                + trigger_agent = scenario_import.scenario.agents.find_by(:guid => "a-trigger-agent")  | 
            |
| 242 | 
                +  | 
            |
| 243 | 
                + expect(weather_agent.keep_events_for).to eq(2.days)  | 
            |
| 244 | 
                + expect(trigger_agent.keep_events_for).to eq(0)  | 
            |
| 245 | 
                + end  | 
            |
| 246 | 
                + end  | 
            |
| 229 | 247 | 
                end  | 
            
| 230 | 248 | 
                 | 
            
| 231 | 249 | 
                describe "#generate_diff" do  | 
            
                @@ -309,7 +327,7 @@ describe ScenarioImport do  | 
            ||
| 309 | 327 | 
                 | 
            
| 310 | 328 | 
                           expect(weather_agent.name).to eq("a weather agent")
               | 
            
| 311 | 329 | 
                           expect(weather_agent.schedule).to eq("5pm")
               | 
            
| 312 | 
                - expect(weather_agent.keep_events_for).to eq(14)  | 
            |
| 330 | 
                + expect(weather_agent.keep_events_for).to eq(14.days)  | 
            |
| 313 | 331 | 
                expect(weather_agent.propagate_immediately).to be_falsey  | 
            
| 314 | 332 | 
                expect(weather_agent).to be_disabled  | 
            
| 315 | 333 | 
                expect(weather_agent.memory).to be_empty  | 
            
                @@ -330,7 +348,7 @@ describe ScenarioImport do  | 
            ||
| 330 | 348 | 
                             "0" => {
               | 
            
| 331 | 349 | 
                "name" => "updated name",  | 
            
| 332 | 350 | 
                "schedule" => "6pm",  | 
            
| 333 | 
                - "keep_events_for" => "2",  | 
            |
| 351 | 
                + "keep_events_for" => 2.days.to_i,  | 
            |
| 334 | 352 | 
                "disabled" => "false",  | 
            
| 335 | 353 | 
                               "options" => weather_agent_options.merge("api_key" => "foo").to_json
               | 
            
| 336 | 354 | 
                }  | 
            
                @@ -343,7 +361,7 @@ describe ScenarioImport do  | 
            ||
| 343 | 361 | 
                weather_agent = existing_scenario.agents.find_by(:guid => "a-weather-agent")  | 
            
| 344 | 362 | 
                           expect(weather_agent.name).to eq("updated name")
               | 
            
| 345 | 363 | 
                           expect(weather_agent.schedule).to eq("6pm")
               | 
            
| 346 | 
                - expect(weather_agent.keep_events_for).to eq(2)  | 
            |
| 364 | 
                + expect(weather_agent.keep_events_for).to eq(2.days)  | 
            |
| 347 | 365 | 
                expect(weather_agent).not_to be_disabled  | 
            
| 348 | 366 | 
                           expect(weather_agent.options).to eq(weather_agent_options.merge("api_key" => "foo"))
               | 
            
| 349 | 367 | 
                end  | 
            
                @@ -353,7 +371,7 @@ describe ScenarioImport do  | 
            ||
| 353 | 371 | 
                             "0" => {
               | 
            
| 354 | 372 | 
                "name" => "",  | 
            
| 355 | 373 | 
                "schedule" => "foo",  | 
            
| 356 | 
                - "keep_events_for" => "2",  | 
            |
| 374 | 
                + "keep_events_for" => 2.days.to_i.to_s,  | 
            |
| 357 | 375 | 
                               "options" => weather_agent_options.merge("api_key" => "").to_json
               | 
            
| 358 | 376 | 
                }  | 
            
| 359 | 377 | 
                }  | 
            
                @@ -386,12 +404,40 @@ describe ScenarioImport do  | 
            ||
| 386 | 404 | 
                end  | 
            
| 387 | 405 | 
                end  | 
            
| 388 | 406 | 
                 | 
            
| 407 | 
                + context "when the schema_version is less than 1" do  | 
            |
| 408 | 
                + it "translates keep_events_for from days to seconds" do  | 
            |
| 409 | 
                + valid_parsed_data.delete(:schema_version)  | 
            |
| 410 | 
                + valid_parsed_data[:agents] = [valid_parsed_weather_agent_data.merge(keep_events_for: 5)]  | 
            |
| 411 | 
                +  | 
            |
| 412 | 
                +            scenario_import.merges = {
               | 
            |
| 413 | 
                +              "0" => {
               | 
            |
| 414 | 
                + "name" => "a new name",  | 
            |
| 415 | 
                + "schedule" => "6pm",  | 
            |
| 416 | 
                + "keep_events_for" => 2.days.to_i.to_s,  | 
            |
| 417 | 
                + "disabled" => "true",  | 
            |
| 418 | 
                +                "options" => weather_agent_options.merge("api_key" => "foo").to_json
               | 
            |
| 419 | 
                + }  | 
            |
| 420 | 
                + }  | 
            |
| 421 | 
                +  | 
            |
| 422 | 
                + expect(scenario_import).to be_valid  | 
            |
| 423 | 
                +  | 
            |
| 424 | 
                + weather_agent_diff = scenario_import.agent_diffs[0]  | 
            |
| 425 | 
                +  | 
            |
| 426 | 
                + expect(weather_agent_diff.name.current).to eq(agents(:bob_weather_agent).name)  | 
            |
| 427 | 
                +            expect(weather_agent_diff.name.incoming).to eq('a weather agent')
               | 
            |
| 428 | 
                +            expect(weather_agent_diff.name.updated).to eq('a new name')
               | 
            |
| 429 | 
                + expect(weather_agent_diff.keep_events_for.current).to eq(45.days.to_i)  | 
            |
| 430 | 
                + expect(weather_agent_diff.keep_events_for.incoming).to eq(5.days.to_i)  | 
            |
| 431 | 
                + expect(weather_agent_diff.keep_events_for.updated).to eq(2.days.to_i.to_s)  | 
            |
| 432 | 
                + end  | 
            |
| 433 | 
                + end  | 
            |
| 434 | 
                +  | 
            |
| 389 | 435 | 
                it "sets the 'updated' FieldDiff values based on any feedback from the user" do  | 
            
| 390 | 436 | 
                           scenario_import.merges = {
               | 
            
| 391 | 437 | 
                             "0" => {
               | 
            
| 392 | 438 | 
                "name" => "a new name",  | 
            
| 393 | 439 | 
                "schedule" => "6pm",  | 
            
| 394 | 
                - "keep_events_for" => "2",  | 
            |
| 440 | 
                + "keep_events_for" => 2.days.to_s,  | 
            |
| 395 | 441 | 
                "disabled" => "true",  | 
            
| 396 | 442 | 
                               "options" => weather_agent_options.merge("api_key" => "foo").to_json
               | 
            
| 397 | 443 | 
                },  | 
            
                @@ -411,7 +457,8 @@ describe ScenarioImport do  | 
            ||
| 411 | 457 | 
                           expect(weather_agent_diff.name.updated).to eq("a new name")
               | 
            
| 412 | 458 | 
                 | 
            
| 413 | 459 | 
                           expect(weather_agent_diff.schedule.updated).to eq("6pm")
               | 
            
| 414 | 
                -          expect(weather_agent_diff.keep_events_for.updated).to eq("2")
               | 
            |
| 460 | 
                + expect(weather_agent_diff.keep_events_for.current).to eq(45.days)  | 
            |
| 461 | 
                + expect(weather_agent_diff.keep_events_for.updated).to eq(2.days.to_s)  | 
            |
| 415 | 462 | 
                           expect(weather_agent_diff.disabled.updated).to eq("true")
               | 
            
| 416 | 463 | 
                           expect(weather_agent_diff.options.updated).to eq(weather_agent_options.merge("api_key" => "foo"))
               | 
            
| 417 | 464 | 
                end  |