zooniverse/Cellect

View on GitHub
lib/cellect/server/user.rb

Summary

Maintainability
A
0 mins
Test Coverage
module Cellect
  module Server
    class User
      include Celluloid
      include Celluloid::Logger

      # Gracefully exit when the actor dies
      trap_exit :workflow_crashed
      finalizer :cancel_ttl_timer

      attr_accessor :id, :workflow_name, :seen, :state
      attr_accessor :ttl, :ttl_timer

      # Sets up a new user with an empty seen set, then loads the actual data
      def initialize(id, workflow_name: nil, ttl: nil)
        self.id = id
        self.workflow_name = workflow_name
        self.seen = DiffSet::RandomSet.new
        monitor Workflow[workflow_name]
        @ttl = ttl
        self.state = :initializing
      end

      # Load the seen subjects for a user and restarts the TTL
      def load_data
        return if self.state == :ready
        self.state = :loading
        data = Cellect::Server.adapter.load_user(workflow_name, id) || []
        data.each do |subject_id|
          @seen.add subject_id
        end
        self.state = :ready
        restart_ttl_timer
      end

      # Returns the seen subjects set
      def seen
        restart_ttl_timer
        @seen
      end

      # (Re)starts the inactivity countdown
      def restart_ttl_timer
        self.ttl_timer ||= after(ttl){ ttl_expired! }
        ttl_timer.reset
      end

      # Releases the timer
      def cancel_ttl_timer
        ttl_timer.cancel if ttl_timer
        self.ttl_timer = nil
      end

      # Removes the user from inactivity
      def ttl_expired!
        debug "User #{ id } TTL expired"
        cancel_ttl_timer
        Workflow[workflow_name].async.remove_user(id)
      end

      def ttl
        @ttl || 60 * 15 # 15 minutes
      end

      # Handle errors and let the actor die
      def workflow_crashed(actor, reason)
        cancel_ttl_timer
        terminate
      end
    end
  end
end