Skip to content

Commit

Permalink
Merge 276d593 into bdc1f3f
Browse files Browse the repository at this point in the history
  • Loading branch information
cantino committed Jan 5, 2014
2 parents bdc1f3f + 276d593 commit 46ba8e4
Show file tree
Hide file tree
Showing 16 changed files with 314 additions and 110 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Changes

* 0.31 (Jan 2, 2014) - Agents now have an optional keep\_events\_for option that is propagated to created events' expires\_at field, and they update their events' expires\_at fields on change.
* 0.3 (Jan 1, 2014) - Remove symbolization of memory, options, and payloads; convert memory, options, and payloads to JSON from YAML. Migration will perform conversion and adjust tables to be UTF-8. Recommend making a DB backup before migrating.
* 0.2 (Nov 6, 2013) - PeakDetectorAgent now uses `window_duration_in_days` and `min_peak_spacing_in_days`. Additionally, peaks trigger when the time series rises over the standard deviation multiple, not after it starts to fall.
* June 29, 2013 - Removed rails\_admin because it was causing deployment issues. Better to have people install their favorite admin tool if they want one.
Expand Down
17 changes: 17 additions & 0 deletions app/assets/javascripts/application.js.coffee.erb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ showLinks = ->
$(".link-region .cannot-receive-events").hide()
showEventDescriptions()

hideEventCreation = ->
$(".event-related-region").hide()

showEventCreation = ->
$(".event-related-region").show()

showEventDescriptions = ->
if $("#agent_source_ids").val()
$.getJSON "/agents/event_descriptions", { ids: $("#agent_source_ids").val().join(",") }, (json) =>
Expand Down Expand Up @@ -132,6 +138,11 @@ $(document).ready ->
else
hideLinks()

if json.can_create_events
showEventCreation()
else
hideEventCreation()

$(".description").html(json.description_html) if json.description_html?

if $("#agent_options").hasClass("showing-default") || $("#agent_options").val().match(/\A\s*(\{\s*\}|)\s*\Z/g)
Expand All @@ -153,3 +164,9 @@ $(document).ready ->
showLinks()
else
hideLinks()

if $(".event-related-region")
if $(".event-related-region").data("can-create-events") == true
showEventCreation()
else
hideEventCreation()
1 change: 1 addition & 0 deletions app/controllers/agents_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def type_details
render :json => {
:can_be_scheduled => agent.can_be_scheduled?,
:can_receive_events => agent.can_receive_events?,
:can_create_events => agent.can_create_events?,
:options => agent.default_options,
:description_html => agent.html_description
}
Expand Down
75 changes: 49 additions & 26 deletions app/models/agent.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ class Agent < ActiveRecord::Base
SCHEDULES = %w[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]

attr_accessible :options, :memory, :name, :type, :schedule, :source_ids
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] })]

attr_accessible :options, :memory, :name, :type, :schedule, :source_ids, :keep_events_for

json_serialize :options, :memory

validates_presence_of :name, :user
validates_inclusion_of :keep_events_for, :in => EVENT_RETENTION_SCHEDULES.map(&:last)
validate :sources_are_owned
validate :validate_schedule
validate :validate_options
Expand All @@ -29,6 +32,7 @@ class Agent < ActiveRecord::Base
before_validation :unschedule_if_cannot_schedule
before_save :unschedule_if_cannot_schedule
before_create :set_last_checked_event_id
after_save :possibly_update_event_expirations

belongs_to :user, :inverse_of => :agents
has_many :events, :dependent => :delete_all, :inverse_of => :agent, :order => "events.id desc"
Expand Down Expand Up @@ -87,21 +91,23 @@ def recent_error_logs?
last_event_at && last_error_log_at && last_error_log_at > (last_event_at - 2.minutes)
end

def sources_are_owned
errors.add(:sources, "must be owned by you") unless sources.all? {|s| s.user == user }
end

def create_event(attrs)
if can_create_events?
events.create!({ :user => user }.merge(attrs))
events.create!({ :user => user, :expires_at => new_event_expiration_date }.merge(attrs))
else
error "This Agent cannot create events!"
end
end

def validate_schedule
unless cannot_be_scheduled?
errors.add(:schedule, "is not a valid schedule") unless SCHEDULES.include?(schedule.to_s)
def new_event_expiration_date
keep_events_for > 0 ? keep_events_for.days.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 = DATE_ADD(`created_at`, INTERVAL #{keep_events_for.to_i} DAY)"
end
end

Expand All @@ -116,14 +122,6 @@ def trigger_webhook(params)
end
end

def set_default_schedule
self.schedule = default_schedule unless schedule.present? || cannot_be_scheduled?
end

def unschedule_if_cannot_schedule
self.schedule = nil if cannot_be_scheduled?
end

def default_schedule
self.class.default_schedule
end
Expand Down Expand Up @@ -152,27 +150,52 @@ def can_create_events?
!cannot_create_events?
end

def set_last_checked_event_id
if newest_event_id = Event.order("id desc").limit(1).pluck(:id).first
self.last_checked_event_id = newest_event_id
end
def log(message, options = {})
puts "Agent##{id}: #{message}" unless Rails.env.test?
AgentLog.log_for_agent(self, message, options)
end

def error(message, options = {})
log(message, options.merge(:level => 4))
end

def delete_logs!
logs.delete_all
update_column :last_error_log_at, nil
end

def log(message, options = {})
puts "Agent##{id}: #{message}" unless Rails.env.test?
AgentLog.log_for_agent(self, message, options)
# Validations and Callbacks

def sources_are_owned
errors.add(:sources, "must be owned by you") unless sources.all? {|s| s.user == user }
end

def error(message, options = {})
log(message, options.merge(:level => 4))
def validate_schedule
unless cannot_be_scheduled?
errors.add(:schedule, "is not a valid schedule") unless SCHEDULES.include?(schedule.to_s)
end
end

def set_default_schedule
self.schedule = default_schedule unless schedule.present? || cannot_be_scheduled?
end

def unschedule_if_cannot_schedule
self.schedule = nil if cannot_be_scheduled?
end

def set_last_checked_event_id
if newest_event_id = Event.order("id desc").limit(1).pluck(:id).first
self.last_checked_event_id = newest_event_id
end
end

def possibly_update_event_expirations
update_event_expirations! if keep_events_for_changed?
end

# Class Methods

class << self
def cannot_be_scheduled!
@cannot_be_scheduled = true
Expand Down
2 changes: 2 additions & 0 deletions app/models/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ def reemit!
end

def self.cleanup_expired!
affected_agents = Event.where("expires_at IS NOT NULL AND expires_at < ?", Time.now).group("agent_id").pluck(:agent_id)
Event.where("expires_at IS NOT NULL AND expires_at < ?", Time.now).delete_all
Agent.where(:id => affected_agents).update_all "events_count = (select count(*) from events where agent_id = agents.id)"
end
end
10 changes: 10 additions & 0 deletions app/views/agents/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@
</div>
</div>


<div class='event-related-region' data-can-create-events="<%= @agent.can_create_events? %>">
<div class="control-group">
<%= f.label :keep_events_for, "Keep events", :class => 'control-label' %>
<div class="controls">
<%= f.select :keep_events_for, options_for_select(Agent::EVENT_RETENTION_SCHEDULES, @agent.keep_events_for), {}, :class => 'span4' %>
</div>
</div>
</div>

<div class="control-group">
<%= f.label :sources, :class => 'control-label' %>
<div class="controls link-region" data-can-receive-events="<%= @agent.can_receive_events? %>">
Expand Down
5 changes: 5 additions & 0 deletions app/views/agents/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@
<% end %>
<% if @agent.can_create_events? %>
<p>
<b>Keep events:</b>
<%= (Agent::EVENT_RETENTION_SCHEDULES.detect {|s| s.last == @agent.keep_events_for } || [@agent.keep_events_for]).first %>
</p>

<p>
<b>Last event created:</b>
<%= @agent.last_event_at ? time_ago_in_words(@agent.last_event_at) + " ago" : "never" %>
Expand Down
5 changes: 5 additions & 0 deletions app/views/events/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
<h2>Event from <%= @event.agent.name %></h2>
</div>

<p>
<b>Expires in:</b>
<%= @event.expires_at ? time_ago_in_words(@event.expires_at) : 'never' %>
</p>

<p>
<b>Payload:</b>
<pre><%= Utils.pretty_jsonify @event.payload || {} %></pre>
Expand Down
5 changes: 3 additions & 2 deletions app/views/home/_signed_out_index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
<div class='row'>
<div class="span5 offset2">
<h1>Your agents are standing by</h1>
<p>Know the world around you</p>
<p>Huginn monitors the world and acts on your behalf.</p>

<%= link_to "Signup", new_user_registration_path, :class => "btn btn-primary btn-large center" %>
<%= link_to "Login", new_user_session_path, :class => "btn btn-large" %>
<%= link_to "Signup", new_user_registration_path, :class => "btn btn-primary btn-large" %>
</div>
<div class="span3">
<%= image_tag 'odin.jpg', :class => 'img-rounded', :title => "Wägner, Wilhelm. 1882. Nordisch-germanische Götter und Helden. Otto Spamer, Leipzig & Berlin. Page 7." %>
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20131222211558_add_keep_events_for_to_agents.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddKeepEventsForToAgents < ActiveRecord::Migration
def change
add_column :agents, :keep_events_for, :integer, :null => false, :default => 0
end
end
9 changes: 6 additions & 3 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.

ActiveRecord::Schema.define(:version => 20131105063248) do
ActiveRecord::Schema.define(:version => 20131227000021) do

create_table "agent_logs", :force => true do |t|
t.integer "agent_id", :null => false
Expand All @@ -33,10 +33,13 @@
t.datetime "last_check_at"
t.datetime "last_receive_at"
t.integer "last_checked_event_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.text "memory", :limit => 2147483647
t.datetime "last_webhook_at"
t.datetime "last_event_at"
t.datetime "last_error_log_at"
t.integer "keep_events_for", :default => 0, :null => false
end

add_index "agents", ["schedule"], :name => "index_agents_on_schedule"
Expand Down
2 changes: 1 addition & 1 deletion spec/controllers/events_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
}.should change { Event.count }.by(1)
Event.last.payload.should == events(:bob_website_agent_event).payload
Event.last.agent.should == events(:bob_website_agent_event).agent
Event.last.created_at.should be_within(1).of(Time.now)
Event.last.created_at.to_i.should be_within(2).of(Time.now.to_i)
end

it "can only re-emit Events for the current user" do
Expand Down
4 changes: 4 additions & 0 deletions spec/fixtures/agents.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
jane_website_agent:
type: Agents::WebsiteAgent
user: jane
events_count: 1
schedule: "5pm"
name: "ZKCD"
options: <%= {
Expand All @@ -16,6 +17,7 @@ jane_website_agent:
bob_website_agent:
type: Agents::WebsiteAgent
user: bob
events_count: 1
schedule: "midnight"
name: "ZKCD"
options: <%= {
Expand All @@ -33,6 +35,7 @@ bob_weather_agent:
user: bob
schedule: "midnight"
name: "SF Weather"
keep_events_for: 45
options: <%= {
:location => 94102,
:lat => 37.779329,
Expand All @@ -45,6 +48,7 @@ jane_weather_agent:
user: jane
schedule: "midnight"
name: "SF Weather"
keep_events_for: 30
options: <%= {
:location => 94103,
:lat => 37.779329,
Expand Down

0 comments on commit 46ba8e4

Please sign in to comment.