Rewrite of session backend.

This commit is contained in:
Martin Edenhofer 2014-07-13 20:52:32 +02:00
parent d9c3a7de21
commit 014ff4bda2
27 changed files with 1290 additions and 644 deletions

View file

@ -19,16 +19,16 @@ module ExtraCollection
def push( collections, user )
# all base stuff
collections[ Role.to_app_model ] = Role.all
collections[ Group.to_app_model ] = Group.all
#collections[ Role.to_app_model ] = Role.all
#collections[ Group.to_app_model ] = Group.all
if !user.is_role('Customer')
collections[ Organization.to_app_model ] = Organization.all
else
if user.organization_id
collections[ Organization.to_app_model ] = Organization.where( :id => user.organization_id )
end
end
#if !user.is_role('Customer')
# collections[ Organization.to_app_model ] = Organization.all
#else
# if user.organization_id
# collections[ Organization.to_app_model ] = Organization.where( :id => user.organization_id )
# end
#end
end
module_function :session, :push
end

View file

@ -22,20 +22,20 @@ module ExtraCollection
def push( collections, user )
# all ticket stuff
collections[ Ticket::StateType.to_app_model ] = Ticket::StateType.all
collections[ Ticket::State.to_app_model ] = Ticket::State.all
collections[ Ticket::Priority.to_app_model ] = Ticket::Priority.all
collections[ Ticket::Article::Type.to_app_model ] = Ticket::Article::Type.all
collections[ Ticket::Article::Sender.to_app_model ] = Ticket::Article::Sender.all
#collections[ Ticket::StateType.to_app_model ] = Ticket::StateType.all
#collections[ Ticket::State.to_app_model ] = Ticket::State.all
#collections[ Ticket::Priority.to_app_model ] = Ticket::Priority.all
#collections[ Ticket::Article::Type.to_app_model ] = Ticket::Article::Type.all
#collections[ Ticket::Article::Sender.to_app_model ] = Ticket::Article::Sender.all
if !user.is_role('Customer')
#if !user.is_role('Customer')
# all signatures
collections[ Signature.to_app_model ] = Signature.all
# collections[ Signature.to_app_model ] = Signature.all
# all email addresses
collections[ EmailAddress.to_app_model ] = EmailAddress.all
end
# collections[ EmailAddress.to_app_model ] = EmailAddress.all
#end
end
module_function :session, :push

View file

@ -37,7 +37,7 @@ class RecentView < ApplicationModel
data.delete( 'history_object_id' )
list.push data
}
return list
list
end
def self.list_fulldata( user, limit = 10 )

View file

@ -14,7 +14,6 @@ module Sessions
@pid = @root + '/tmp/pids/sessionworker.pid'
# create global vars for threads
@@user_threads = {}
@@client_threads = {}
=begin
@ -458,23 +457,6 @@ returns
user = User.find( session_data[:user][:id] )
next if !user
# start user thread
start_user_thread = false
if !@@user_threads[user.id]
@@user_threads[user.id] = true
@@user_threads[user.id] = Thread.new {
thread_worker(user.id)
@@user_threads[user.id] = nil
puts "close user (#{user.id}) thread"
}
start_user_thread = true
end
# wait with client thread unil user thread has done some little work
if start_user_thread
sleep 0.5
end
# start client thread
if !@@client_threads[client_id]
@@client_threads[client_id] = true
@ -493,68 +475,6 @@ returns
=begin
check if worker for user is running
Sessions.thread_worker_exists?(user)
returns
thread
=end
def self.thread_worker_exists?(user)
@@user_threads[user.id]
end
=begin
start worker for user
Sessions.thread_worker(user.id)
returns
thread
=end
def self.thread_worker(user_id, try_count = 0, try_run_time = Time.now)
puts "LOOP WORKER #{user_id} - #{try_count}"
begin
Sessions::Worker.new(user_id)
rescue => e
puts "thread_worker exited with error #{ e.inspect }"
sleep 10
begin
# ActiveRecord::Base.remove_connection
# ActiveRecord::Base.connection_pool.reap
ActiveRecord::Base.connection_pool.release_connection
rescue => e
puts "Can't reconnect to database #{ e.inspect }"
end
try_run_max = 10
try_count += 1
# reset error counter if to old
if try_run_time + ( 60 * 5 ) < Time.now
try_count = 0
end
try_run_time = Time.now
# restart worker again
if try_run_max > try_count
thread_worker(user_id, try_count, try_run_time)
else
raise "STOP thread_worker for user #{user_id} after #{try_run_max} tries"
end
end
puts "/LOOP WORKER #{user_id} - #{try_count}"
end
=begin
check if thread for client_id is running
Sessions.thread_client_exists?(client_id)
@ -587,6 +507,7 @@ returns
Sessions::Client.new(client_id)
rescue => e
puts "thread_client exited with error #{ e.inspect }"
puts e.backtrace.join("\n ")
sleep 10
begin
# ActiveRecord::Base.remove_connection

View file

@ -1,38 +1,63 @@
module Sessions::Backend::ActivityStream
class Sessions::Backend::ActivityStream
def self.worker( user, worker )
cache_key = 'user_' + user.id.to_s + '_activity_stream'
if Sessions::CacheIn.expired(cache_key)
activity_stream = user.activity_stream( 20 )
activity_stream_cache = Sessions::CacheIn.get( cache_key, { :re_expire => true } )
worker.log 'notice', 'fetch activity_stream - ' + cache_key
if activity_stream != activity_stream_cache
worker.log 'notify', 'fetch activity_stream changed - ' + cache_key
activity_stream_full = user.activity_stream( 20, true )
Sessions::CacheIn.set( cache_key, activity_stream, { :expires_in => 0.75.minutes } )
Sessions::CacheIn.set( cache_key + '_push', activity_stream_full )
end
end
def initialize( user, client = nil, client_id = nil )
@user = user
@client = client
@client_id = client_id
@last_change = nil
end
def self.push( user, client )
cache_key = 'user_' + user.id.to_s + '_activity_stream'
def load
activity_stream_time = Sessions::CacheIn.get_time( cache_key, { :ignore_expire => true } )
if activity_stream_time && client.last_change['activity_stream'] != activity_stream_time
client.last_change['activity_stream'] = activity_stream_time
activity_stream = Sessions::CacheIn.get( cache_key, { :ignore_expire => true } )
client.log 'notify', "push activity_stream for user #{user.id}"
# send update to browser
r = Sessions::CacheIn.get( cache_key + '_push', { :ignore_expire => true } )
client.send({
:event => 'activity_stream_rebuild',
:collection => 'activity_stream',
:data => r,
})
# get whole collection
activity_stream = @user.activity_stream( 25 )
if activity_stream && !activity_stream.first
return
end
if activity_stream && activity_stream.first && activity_stream.first['created_at'] == @last_change
return
end
# update last changed
if activity_stream && activity_stream.first
@last_change = activity_stream.first['created_at']
end
@user.activity_stream( 25, true )
end
def client_key
"as::load::#{ self.class.to_s }::#{ @user.id }::#{ @client_id }"
end
def push
# check timeout
timeout = Sessions::CacheIn.get( self.client_key )
return if timeout
# set new timeout
Sessions::CacheIn.set( self.client_key, true, { :expires_in => 0.5.minutes } )
data = self.load
return if !data||data.empty?
if !@client
return {
:event => 'activity_stream_rebuild',
:collection => 'activity_stream',
:data => data,
}
end
@client.log 'notify', "push activity_stream #{ data.first.class.to_s } for user #{ @user.id }"
@client.send({
:event => 'activity_stream_rebuild',
:collection => 'activity_stream',
:data => data,
})
end
end

View file

@ -1,71 +1,47 @@
module Sessions::Backend::Collections
@@last_change = {}
def self.worker( user, worker )
worker.log 'notice', "---user - fetch push_collection data"
# get available collections
cache_key = 'user_' + user.id.to_s + '_push_collections'
collections = Sessions::CacheIn.get( cache_key )
if !collections
collections = {}
push_collection = SessionHelper::push_collections(user)
push_collection.each { | key, value |
collections[ key ] = true
}
Sessions::CacheIn.set( cache_key, collections, { :expires_in => 2.minutes } )
end
# check all collections to push
push_collection = {}
collections.each { | key, v |
cache_key = 'user_' + user.id.to_s + '_push_collections_' + key.to_s
if Sessions::CacheIn.expired(cache_key)
if push_collection.empty?
push_collection = SessionHelper::push_collections(user)
end
push_collection_cache = Sessions::CacheIn.get( cache_key, { :re_expire => true } )
worker.log 'notice', "---user - fetch push_collection data " + cache_key
# if !push_collection[key] || !push_collection_cache || push_collection[key] != push_collection_cache || !push_collection[ key ].zip( push_collection_cache ).all? { |x, y| x.attributes == y.attributes }
if !push_collection[key] || !push_collection_cache || push_collection[key] != push_collection_cache || !push_collection[ key ].zip( push_collection_cache ).all? { |x, y| return false if !x; return false if !y; x.attributes == y.attributes }
worker.log 'notify', 'fetch push_collection changed - ' + cache_key
Sessions::CacheIn.set( cache_key, push_collection[key], { :expires_in => 1.minutes } )
end
end
}
class Sessions::Backend::Collections
def initialize( user, client, client_id )
@user = user
@client = client
@client_id = client_id
@backends = self.backend
end
def self.push( user, client )
cache_key = 'user_' + user.id.to_s + '_push_collections'
if !client.last_change['push_collections']
client.last_change['push_collections'] = {}
end
collections = Sessions::CacheIn.get( cache_key ) || {}
collections.each { | key, v |
collection_cache_key = 'user_' + user.id.to_s + '_push_collections_' + key.to_s
collection_time = Sessions::CacheIn.get_time( collection_cache_key, { :ignore_expire => true } )
if collection_time && client.last_change['push_collections'][ key ] != collection_time
client.last_change['push_collections'][ key ] = collection_time
push_collections = Sessions::CacheIn.get( collection_cache_key, { :ignore_expire => true } )
client.log 'notify', "push push_collections #{key} for user #{user.id}"
# send update to browser
data = {}
data[key] = push_collections
client.send({
:event => 'resetCollection',
:data => data,
})
def push
results = []
@backends.each {|backend|
#puts "B: #{backend.inspect}"
result = backend.push
#puts "R: #{result.inspect}"
if result
results.push result
end
}
results
end
def backend
# auto population collections
backends = []
# load collections to deliver from external files
dir = File.expand_path('../../../../', __FILE__)
files = Dir.glob( "#{dir}/lib/sessions/backend/collections/*.rb" )
for file in files
file.gsub!("#{dir}/lib/", '')
file.gsub!(/\.rb$/, '')
next if file.classify == 'Sessions::Backend::Collections::Base'
#puts "LOAD #{file.classify}---"
#next if file == ''
backend = file.classify.constantize.new(@user, @client, @client_id)
if backend
backends.push backend
end
end
backends
end
end

View file

@ -0,0 +1,137 @@
class Sessions::Backend::Collections::Base
class << self; attr_accessor :model, :is_role, :is_not_role end
def initialize( user, client = nil, client_id = nil )
@user = user
@client = client
@client_id = client_id
@last_change = nil
end
def collection_key
"collections::load::#{ self.class.to_s }::#{ @user.id }"
end
def load
#puts "-LOAD--------#{self.collection_key}"
# check timeout
cache = Sessions::CacheIn.get( self.collection_key )
return cache if @last_change && cache
#puts "---REAL FETCH #{@user.id}"
# update last changed
last = self.class.model.constantize.select('updated_at').order('updated_at DESC').first
if last
@last_change = last.updated_at
end
# if no entry exists, remember last check
if !@last_change
@last_change = Time.now
end
# get whole collection
all = self.class.model.constantize.all
# set new timeout
Sessions::CacheIn.set( self.collection_key, all, { :expires_in => 10.minutes } )
all
end
def changed?
# if no data has been delivered till now
return true if !@last_change
# check if update has been done
last = self.class.model.constantize.select('updated_at').order('updated_at DESC').first
return false if !last
return false if last.updated_at == @last_change
# delete collection cache
Sessions::CacheIn.delete( self.collection_key )
# collection has changed
true
end
def client_key
"collections::load::#{ self.class.to_s }::#{ @user.id }::#{ @client_id }"
end
def push
# check role based access
if self.class.is_role
access = nil
self.class.is_role.each {|role|
if @user.is_role(role)
access = true
end
}
return if !access
end
if self.class.is_not_role
self.class.is_not_role.each {|role|
return if @user.is_role(role)
}
end
# check timeout
timeout = Sessions::CacheIn.get( self.client_key )
return if timeout
# set new timeout
Sessions::CacheIn.set( self.client_key, true, { :expires_in => 10.seconds } )
return if !self.changed?
data = self.load
return if !data||data.empty?
# collect assets
assets = {}
data.each {|item|
assets = item.assets(assets)
}
if !@client
return {
:collection => {
data.first.class.to_app_model => data,
},
:assets => assets,
}
end
@client.log 'notify', "push assets for push_collection #{ data.first.class.to_s } for user #{ @user.id }"
@client.send({
:data => assets,
:event => [ 'loadAssets' ],
})
@client.log 'notify', "push push_collection #{ data.first.class.to_s } for user #{ @user.id }"
@client.send({
:event => 'resetCollection',
:data => {
data.first.class.to_app_model => data,
},
})
end
def self.model_set(model)
@model = model
end
def self.is_role_set(role)
if !@is_role
@is_role = []
end
@is_role.push role
end
def self.is_not_role_set(role)
if !@is_not_role
@is_not_role = []
end
@is_not_role.push role
end
end

View file

@ -0,0 +1,4 @@
class Sessions::Backend::Collections::EmailAddress < Sessions::Backend::Collections::Base
model_set 'EmailAddress'
is_not_role_set 'Customer'
end

View file

@ -0,0 +1,3 @@
class Sessions::Backend::Collections::Group < Sessions::Backend::Collections::Base
model_set 'Group'
end

View file

@ -0,0 +1,67 @@
class Sessions::Backend::Collections::Organization < Sessions::Backend::Collections::Base
model_set 'Organization'
def load
# check timeout
cache = Sessions::CacheIn.get( self.collection_key )
return cache if @last_change && cache
# update last changed
if !@user.is_role('Customer')
last = self.class.model.constantize.select('updated_at').order('updated_at DESC').first
if last
@last_change = last.updated_at
end
else
if @user.organization_id
last = Organization.where( :id => @user.organization_id ).first
@last_change = last.updated_at
end
end
# if no entry exists, remember last check
if !@last_change
@last_change = Time.now
end
# get whole collection
all = []
if !@user.is_role('Customer')
all = Organization.all
else
if @user.organization_id
all = Organization.where( :id => @user.organization_id )
end
end
# set new timeout
Sessions::CacheIn.set( self.collection_key, all, { :expires_in => 10.minutes } )
all
end
def changed?
# if no data has been delivered till now
return true if !@last_change
# check if update has been done
if !@user.is_role('Customer')
last = self.class.model.constantize.select('updated_at').order('updated_at DESC').first
else
if @user.organization_id
last = Organization.where( :id => @user.organization_id ).first
end
end
return false if !last
return false if last.updated_at == @last_change
# delete collection cache
Sessions::CacheIn.delete( self.collection_key )
# collection has changed
true
end
end

View file

@ -0,0 +1,3 @@
class Sessions::Backend::Collections::Role < Sessions::Backend::Collections::Base
model_set 'Role'
end

View file

@ -0,0 +1,4 @@
class Sessions::Backend::Collections::Signature < Sessions::Backend::Collections::Base
model_set 'Signature'
is_not_role_set 'Customer'
end

View file

@ -0,0 +1,3 @@
class Sessions::Backend::Collections::TicketArticleSender < Sessions::Backend::Collections::Base
model_set 'Ticket::Article::Sender'
end

View file

@ -0,0 +1,3 @@
class Sessions::Backend::Collections::TicketArticleType < Sessions::Backend::Collections::Base
model_set 'Ticket::Article::Type'
end

View file

@ -0,0 +1,3 @@
class Sessions::Backend::Collections::TicketPriority < Sessions::Backend::Collections::Base
model_set 'Ticket::Priority'
end

View file

@ -0,0 +1,3 @@
class Sessions::Backend::Collections::TicketState < Sessions::Backend::Collections::Base
model_set 'Ticket::State'
end

View file

@ -1,37 +1,59 @@
module Sessions::Backend::RecentViewed
def self.worker( user, worker )
cache_key = 'user_' + user.id.to_s + '_recent_viewed'
if Sessions::CacheIn.expired(cache_key)
recent_viewed = RecentView.list_fulldata( user, 10 )
recent_viewed_cache = Sessions::CacheIn.get( cache_key, { :re_expire => true } )
worker.log 'notice', 'fetch recent_viewed - ' + cache_key
if recent_viewed != recent_viewed_cache
worker.log 'notify', 'fetch recent_viewed changed - ' + cache_key
recent_viewed_full = RecentView.list_fulldata( user, 10 )
Sessions::CacheIn.set( cache_key, recent_viewed, { :expires_in => 5.seconds } )
Sessions::CacheIn.set( cache_key + '_push', recent_viewed_full )
end
end
class Sessions::Backend::RecentViewed
def initialize( user, client = nil, client_id = nil )
@user = user
@client = client
@client_id = client_id
@last_change = nil
end
def self.push( user, client )
cache_key = 'user_' + user.id.to_s + '_recent_viewed'
recent_viewed_time = Sessions::CacheIn.get_time( cache_key, { :ignore_expire => true } )
if recent_viewed_time && client.last_change['recent_viewed'] != recent_viewed_time
client.last_change['recent_viewed'] = recent_viewed_time
recent_viewed = Sessions::CacheIn.get( cache_key, { :ignore_expire => true } )
client.log 'notify', "push recent_viewed for user #{user.id}"
def load
# send update to browser
r = Sessions::CacheIn.get( cache_key + '_push', { :ignore_expire => true } )
client.send({
# get whole collection
recent_viewed = RecentView.list( @user, 10 )
# no data exists
return if !recent_viewed
return if recent_viewed.empty?
# no change exists
return if @last_change == recent_viewed
# remember last state
@last_change = recent_viewed
RecentView.list_fulldata( @user, 10 )
end
def client_key
"as::load::#{ self.class.to_s }::#{ @user.id }::#{ @client_id }"
end
def push
# check timeout
timeout = Sessions::CacheIn.get( self.client_key )
return if timeout
# set new timeout
Sessions::CacheIn.set( self.client_key, true, { :expires_in => 15.seconds } )
data = self.load
return if !data||data.empty?
if !@client
return {
:event => 'update_recent_viewed',
:data => r,
})
:data => data,
}
end
@client.log 'notify', "push recent_viewed for user #{ @user.id }"
@client.send({
:event => 'update_recent_viewed',
:data => data,
})
end
end
end

View file

@ -1,41 +1,63 @@
require 'rss'
module Sessions::Backend::Rss
def self.worker( user, worker )
cache_key = 'user_' + user.id.to_s + '_rss'
if Sessions::CacheIn.expired(cache_key)
url = 'http://www.heise.de/newsticker/heise-atom.xml'
rss_items = Rss.fetch( url, 8 )
rss_items_cache = Sessions::CacheIn.get( cache_key, { :re_expire => true } )
worker.log 'notice', 'fetch rss - ' + cache_key
if rss_items != rss_items_cache
worker.log 'notify', 'fetch rss changed - ' + cache_key
Sessions::CacheIn.set( cache_key, rss_items, { :expires_in => 2.minutes } )
Sessions::CacheIn.set( cache_key + '_push', {
head: 'Heise ATOM',
items: rss_items,
})
end
end
class Sessions::Backend::Rss
def initialize( user, client, client_id )
@user = user
@client = client
@client_id = client_id
end
def self.push( user, client )
cache_key = 'user_' + user.id.to_s + '_rss'
def collection_key
"rss::load::#{ self.class.to_s }::#{ @user.id }"
end
rss_items_time = Sessions::CacheIn.get_time( cache_key, { :ignore_expire => true } )
if rss_items_time && client.last_change['rss'] != rss_items_time
client.last_change['rss'] = rss_items_time
rss_items = Sessions::CacheIn.get( cache_key, { :ignore_expire => true } )
client.log 'notify', "push rss for user #{user.id}"
def load
# send update to browser
r = Sessions::CacheIn.get( cache_key + '_push', { :ignore_expire => true } )
client.send({
# check timeout
cache = Sessions::CacheIn.get( self.collection_key )
return cache if cache
url = 'http://www.heise.de/newsticker/heise-atom.xml'
rss_items = Rss.fetch( url, 8 )
# set new timeout
Sessions::CacheIn.set( self.collection_key, rss_items, { :expires_in => 1.hours } )
rss_items
end
def client_key
"rss::load::#{ self.class.to_s }::#{ @user.id }::#{ @client_id }"
end
def push
# check timeout
timeout = Sessions::CacheIn.get( self.client_key )
return if timeout
# set new timeout
Sessions::CacheIn.set( self.client_key, true, { :expires_in => 5.minutes } )
data = self.load
return if !data||data.empty?
if !@client
return {
:event => 'rss_rebuild',
:collection => 'dashboard_rss',
:data => r,
})
:data => data,
}
end
@client.log 'notify', "push rss for user #{@user.id}"
@client.send({
:event => 'rss_rebuild',
:collection => 'dashboard_rss',
:data => data,
})
end
end

View file

@ -1,47 +1,70 @@
module Sessions::Backend::TicketCreate
def self.worker( user, worker )
cache_key = 'user_' + user.id.to_s + '_ticket_create_attributes'
if Sessions::CacheIn.expired(cache_key)
ticket_create_attributes = Ticket::ScreenOptions.attributes_to_change(
:current_user_id => user.id,
)
ticket_create_attributes_cache = Sessions::CacheIn.get( cache_key, { :re_expire => true } )
worker.log 'notice', 'fetch ticket_create_attributes - ' + cache_key
if ticket_create_attributes != ticket_create_attributes_cache
worker.log 'notify', 'fetch ticket_create_attributes changed - ' + cache_key
Sessions::CacheIn.set( cache_key, ticket_create_attributes, { :expires_in => 2.minutes } )
end
end
class Sessions::Backend::TicketCreate
def initialize( user, client = nil, client_id = nil )
@user = user
@client = client
@client_id = client_id
@last_change = nil
end
def self.push( user, client )
cache_key = 'user_' + user.id.to_s + '_ticket_create_attributes'
def load
ticket_create_attributes_time = Sessions::CacheIn.get_time( cache_key, { :ignore_expire => true } )
if ticket_create_attributes_time && client.last_change['ticket_create_attributes'] != ticket_create_attributes_time
client.last_change['ticket_create_attributes'] = ticket_create_attributes_time
create_attributes = Sessions::CacheIn.get( cache_key, { :ignore_expire => true } )
users = {}
create_attributes[:owner_id].each {|user_id|
if !users[user_id]
users[user_id] = User.user_data_full(user_id)
end
}
data = {
:users => users,
:edit_form => create_attributes,
}
client.log 'notify', "push ticket_create_attributes for user #{user.id}"
# get whole collection
ticket_create_attributes = Ticket::ScreenOptions.attributes_to_change(
:current_user_id => @user.id,
)
# send update to browser
client.send({
# no data exists
return if !ticket_create_attributes
# no change exists
return if @last_change == ticket_create_attributes
# remember last state
@last_change = ticket_create_attributes
ticket_create_attributes
end
def client_key
"as::load::#{ self.class.to_s }::#{ @user.id }::#{ @client_id }"
end
def push
# check timeout
timeout = Sessions::CacheIn.get( self.client_key )
return if timeout
# set new timeout
Sessions::CacheIn.set( self.client_key, true, { :expires_in => 25.seconds } )
create_attributes = self.load
return if !create_attributes
users = {}
create_attributes[:owner_id].each {|user_id|
if !users[user_id]
users[user_id] = User.user_data_full(user_id)
end
}
data = {
:users => users,
:edit_form => create_attributes,
}
if !@client
return {
:collection => 'ticket_create_attributes',
:data => data,
})
:data => create_attributes,
}
end
@client.log 'notify', "push ticket_create for user #{ @user.id }"
@client.send({
:collection => 'ticket_create_attributes',
:data => create_attributes,
})
end
end

View file

@ -1,38 +1,59 @@
module Sessions::Backend::TicketOverviewIndex
def self.worker( user, worker )
cache_key = 'user_' + user.id.to_s + '_overview'
if Sessions::CacheIn.expired(cache_key)
overview = Ticket::Overviews.list(
:current_user => user,
)
overview_cache = Sessions::CacheIn.get( cache_key, { :re_expire => true } )
worker.log 'notice', 'fetch overview - ' + cache_key
if overview != overview_cache
worker.log 'notify', 'fetch overview changed - ' + cache_key
# puts overview.inspect
# puts '------'
# puts overview_cache.inspect
Sessions::CacheIn.set( cache_key, overview, { :expires_in => 4.seconds } )
end
end
class Sessions::Backend::TicketOverviewIndex
def initialize( user, client = nil, client_id = nil )
@user = user
@client = client
@client_id = client_id
@last_change = nil
end
def self.push( user, client )
cache_key = 'user_' + user.id.to_s + '_overview'
overview_time = Sessions::CacheIn.get_time( cache_key, { :ignore_expire => true } )
if overview_time && client.last_change['overview'] != overview_time
client.last_change['overview'] = overview_time
overview = Sessions::CacheIn.get( cache_key, { :ignore_expire => true } )
def load
client.log 'notify', "push overview for user #{user.id}"
# get whole collection
overview = Ticket::Overviews.list(
:current_user => @user,
)
# send update to browser
client.send({
# no data exists
return if !overview
# no change exists
return if @last_change == overview
# remember last state
@last_change = overview
overview
end
def client_key
"as::load::#{ self.class.to_s }::#{ @user.id }::#{ @client_id }"
end
def push
# check timeout
timeout = Sessions::CacheIn.get( self.client_key )
return if timeout
# set new timeout
Sessions::CacheIn.set( self.client_key, true, { :expires_in => 5.seconds } )
data = self.load
return if !data
if !@client
return {
:event => 'navupdate_ticket_overview',
:data => overview,
})
:data => data,
}
end
@client.log 'notify', "push overview_index for user #{ @user.id }"
@client.send({
:event => 'navupdate_ticket_overview',
:data => data,
})
end
end

View file

@ -1,93 +1,113 @@
module Sessions::Backend::TicketOverviewList
def self.worker( user, worker )
overviews = Ticket::Overviews.all(
:current_user => user,
)
overviews.each { |overview|
cache_key = 'user_' + user.id.to_s + '_overview_data_' + overview.link
if Sessions::CacheIn.expired(cache_key)
overview_data = Ticket::Overviews.list(
:view => overview.link,
:current_user => user,
:array => true,
)
overview_data_cache = Sessions::CacheIn.get( cache_key, { :re_expire => true } )
worker.log 'notice', 'fetch overview_data - ' + cache_key
if overview_data != overview_data_cache
worker.log 'notify', 'fetch overview_data changed - ' + cache_key
Sessions::CacheIn.set( cache_key, overview_data, { :expires_in => 5.seconds } )
end
end
}
class Sessions::Backend::TicketOverviewList
def initialize( user, client = nil, client_id = nil )
@user = user
@client = client
@client_id = client_id
@last_change = nil
end
def self.push( user, client )
def load
# get whole collection
overviews = Ticket::Overviews.all(
:current_user => user,
:current_user => @user,
)
# no data exists
return if !overviews
# no change exists
return if @last_change == overviews
# remember last state
@last_change = overviews
overviews
end
def client_key
"as::load::#{ self.class.to_s }::#{ @user.id }::#{ @client_id }"
end
def push
# check timeout
timeout = Sessions::CacheIn.get( self.client_key )
return if timeout
# set new timeout
Sessions::CacheIn.set( self.client_key, true, { :expires_in => 5.seconds } )
overviews = self.load
return if !overviews
# push overviews
overviews.each { |overview|
cache_key = 'user_' + user.id.to_s + '_overview_data_' + overview.link
if !client.last_change['overview_list']
client.last_change['overview_list'] = {}
overview_data = Ticket::Overviews.list(
:view => overview.link,
:current_user => @user,
:array => true,
)
assets = {}
overview_data[:ticket_ids].each {|ticket_id|
ticket = Ticket.find( ticket_id )
assets = ticket.assets(assets)
}
# get groups
group_ids = []
Group.where( :active => true ).each { |group|
group_ids.push group.id
}
agents = {}
Ticket::ScreenOptions.agents.each { |user|
agents[ user.id ] = 1
}
users = {}
groups_users = {}
groups_users[''] = []
group_ids.each {|group_id|
groups_users[ group_id ] = []
Group.find(group_id).users.each {|user|
next if !agents[ user.id ]
groups_users[ group_id ].push user.id
if !users[user.id]
users[user.id] = User.find(user.id)
assets = users[user.id].assets(assets)
end
}
}
if !@client
return {
:event => 'navupdate_ticket_overview',
:data => overview,
}
end
overview_data_time = Sessions::CacheIn.get_time( cache_key, { :ignore_expire => true } )
if overview_data_time && client.last_change['overview_list'][overview.link] != overview_data_time
client.last_change['overview_list'][overview.link] = overview_data_time
overview_data = Sessions::CacheIn.get( cache_key, { :ignore_expire => true } )
client.log 'notify', "push overview_data #{overview.link} for user #{user.id}"
users = {}
tickets = {}
overview_data[:ticket_ids].each {|ticket_id|
client.ticket( ticket_id, tickets, users )
}
@client.log 'notify', "push overview_list for user #{ @user.id }"
# get groups
group_ids = []
Group.where( :active => true ).each { |group|
group_ids.push group.id
}
agents = {}
Ticket::ScreenOptions.agents.each { |user|
agents[ user.id ] = 1
}
groups_users = {}
groups_users[''] = []
group_ids.each {|group_id|
groups_users[ group_id ] = []
Group.find(group_id).users.each {|user|
next if !agents[ user.id ]
groups_users[ group_id ].push user.id
if !users[user.id]
users[user.id] = User.user_data_full(user.id)
end
}
}
# send update to browser
client.send({
:data => {
User.to_app_model => users,
Ticket.to_app_model => tickets,
# send update to browser
@client.send({
:data => assets,
:event => [ 'loadAssets' ]
})
@client.send({
:data => {
:overview => overview_data[:overview],
:ticket_ids => overview_data[:ticket_ids],
:tickets_count => overview_data[:tickets_count],
:bulk => {
:group_id__owner_id => groups_users,
:owner_id => [],
},
:event => [ 'loadAssets' ]
})
client.send({
:data => {
:overview => overview_data[:overview],
:ticket_ids => overview_data[:ticket_ids],
:tickets_count => overview_data[:tickets_count],
:bulk => {
:group_id__owner_id => groups_users,
:owner_id => [],
},
},
:event => [ 'ticket_overview_rebuild' ],
:collection => 'ticket_overview_' + overview.link.to_s,
})
end
},
:event => [ 'ticket_overview_rebuild' ],
:collection => 'ticket_overview_' + overview.link.to_s,
})
}
end

View file

@ -4,6 +4,11 @@ module Sessions::CacheIn
@@expires_in = {}
@@expires_in_ttl = {}
def self.delete( key )
@@data.delete( key )
@@data_time.delete( key )
end
def self.set( key, value, params = {} )
# puts 'CacheIn.set:' + key + '-' + value.inspect
if params[:expires_in]

View file

@ -1,13 +1,7 @@
class Sessions::Client
attr_accessor :last_change
def initialize( client_id )
@client_id = client_id
@cache_key = ''
@data = {}
@pushed = {}
@last_change = {}
self.log 'notify', "---client start ws connection---"
self.fetch
self.log 'notify', "---client exiting ws connection---"
@ -15,6 +9,18 @@ class Sessions::Client
def fetch
backends = [
'Sessions::Backend::TicketOverviewIndex',
'Sessions::Backend::TicketOverviewList',
'Sessions::Backend::Collections',
'Sessions::Backend::Rss',
'Sessions::Backend::ActivityStream',
'Sessions::Backend::RecentViewed',
'Sessions::Backend::TicketCreate',
]
backend_pool = []
user_id_last_run = nil
loop_count = 0
while true
@ -26,83 +32,22 @@ class Sessions::Client
user = User.lookup( :id => session_data[:user][:id] )
return if !user
# set cache key
@cache_key = 'user_' + user.id.to_s
# init new backends
if user_id_last_run != user.id
backend_pool = []
backends.each {|backend|
item = backend.constantize.new(user, self, @client_id)
backend_pool.push item
}
end
loop_count += 1
self.log 'notice', "---client - looking for data of user #{user.id}"
# remember last run
Sessions::CacheIn.set( 'last_run_' + user.id.to_s , true, { :expires_in => 20.seconds } )
# verify already pushed data, send update if needed
if !Sessions::CacheIn.get( 'pushed_users' + @client_id.to_s )
Sessions::CacheIn.set( 'pushed_users' + @client_id.to_s , true, { :expires_in => 60.seconds } )
if @pushed[:users]
users = {}
@pushed[:users].each {|user_id, user_o|
self.user( user_id, users )
}
if !users.empty?
users.each {|user_id, user_data|
self.log 'notify', "push update of already pushed user id #{user_id}"
}
# send update to browser
self.send({
:data => {
User.to_app_model => users,
},
:event => [ 'loadAssets' ],
});
end
end
end
# verify already pushed data, send update if needed
if !Sessions::CacheIn.get( 'pushed_tickets' + @client_id.to_s )
Sessions::CacheIn.set( 'pushed_tickets' + @client_id.to_s , true, { :expires_in => 60.seconds } )
if @pushed[:tickets]
tickets = {}
users = {}
@pushed[:tickets].each {|ticket_id, ticket_data|
self.ticket( ticket_id, tickets, users )
}
if !tickets.empty?
tickets.each {|id, ticket|
self.log 'notify', "push update of already pushed ticket id #{id}"
}
# send update to browser
self.send({
:data => {
Ticket.to_app_model => tickets,
User.to_app_model => users,
},
:event => [ 'loadAssets' ],
});
end
end
end
# overview
Sessions::Backend::TicketOverviewIndex.push( user, self )
# overview_data
Sessions::Backend::TicketOverviewList.push( user, self )
# ticket_create_attributes
Sessions::Backend::TicketCreate.push( user, self )
# recent viewed
Sessions::Backend::RecentViewed.push( user, self )
# activity stream
Sessions::Backend::ActivityStream.push( user, self )
# rss
Sessions::Backend::Rss.push( user, self )
# push_collections
Sessions::Backend::Collections.push( user, self )
# push messages from backends
backend_pool.each {|pool|
pool.push
}
self.log 'notice', "---/client-"
@ -115,44 +60,6 @@ class Sessions::Client
end
end
# add ticket if needed
def ticket( ticket_id, tickets, users )
if !@pushed[:tickets]
@pushed[:tickets] = {}
end
ticket = Ticket.lookup( :id => ticket_id )
if @pushed[:tickets][ticket_id] != ticket['updated_at']
@pushed[:tickets][ticket_id] = ticket['updated_at']
tickets[ticket_id] = ticket
end
# add users if needed
self.user( ticket['owner_id'], users )
self.user( ticket['customer_id'], users )
self.user( ticket['created_by_id'], users )
if ticket['updated_by_id']
self.user( ticket['updated_by_id'], users )
end
end
# add user if needed
def user( user_id, users )
if !@pushed[:users]
@pushed[:users] = {}
end
# get user
user = User.user_data_full( user_id )
# user is already on client and not changed
return if @pushed[:users][ user_id ] == user['updated_at']
@pushed[:users][user_id] = user['updated_at']
# user not on client or different
self.log 'notice', 'push user ... ' + user['login']
users[ user_id ] = user
end
# send update to browser
def send( data )
Sessions.send( @client_id, data )
@ -162,4 +69,4 @@ class Sessions::Client
return if level == 'notice'
puts "#{Time.now}:client(#{ @client_id }) #{ data }"
end
end
end

View file

@ -1,56 +0,0 @@
class Sessions::Worker
def initialize( user_id )
@user_id = user_id
self.log 'notify', "---user started user state"
Sessions::CacheIn.set( 'last_run_' + user_id.to_s , true, { :expires_in => 20.seconds } )
self.fetch( user_id )
end
def fetch(user_id)
while true
user = User.lookup( :id => user_id )
return if !user
# check if user is still with min one open connection
if !Sessions::CacheIn.get( 'last_run_' + user.id.to_s )
self.log 'notify', "---user - closeing thread - no open user connection"
return
end
self.log 'notice', "---user - fetch user data"
# overview
Sessions::Backend::TicketOverviewIndex.worker( user, self )
# overview lists
Sessions::Backend::TicketOverviewList.worker( user, self )
# create_attributes
Sessions::Backend::TicketCreate.worker( user, self )
# recent viewed
Sessions::Backend::RecentViewed.worker( user, self )
# activity steam
Sessions::Backend::ActivityStream.worker( user, self )
# rss
Sessions::Backend::Rss.worker( user, self )
# auto population of default collections
Sessions::Backend::Collections.worker( user, self )
self.log 'notice', "---/user-"
sleep 1
end
end
def log( level, data )
return if level == 'notice'
puts "#{Time.now}:user_id(#{ @user_id }) #{ data }"
end
end

View file

@ -0,0 +1,342 @@
# encoding: utf-8
require 'test_helper'
class SessionBasicTest < ActiveSupport::TestCase
test 'a cache' do
Sessions::CacheIn.set( 'last_run_test' , true, { :expires_in => 2.seconds } )
result = Sessions::CacheIn.get( 'last_run_test' )
assert_equal( true, result, "check 1" )
# should not be expired
result = Sessions::CacheIn.expired( 'last_run_test' )
assert_equal( false, result, "check 1 - expired" )
# should be expired
sleep 3
result = Sessions::CacheIn.expired( 'last_run_test' )
assert_equal( true, result, "check 1 - expired" )
# renew expire
result = Sessions::CacheIn.get( 'last_run_test', :re_expire => true )
assert_equal( true, result, "check 1 - re_expire" )
# should not be expired
result = Sessions::CacheIn.expired( 'last_run_test' )
assert_equal( false, result, "check 1 - expired" )
# ignore expired
sleep 3
result = Sessions::CacheIn.get( 'last_run_test', :ignore_expire => true )
assert_equal( true, result, "check 1 - ignore_expire" )
# should be expired
result = Sessions::CacheIn.expired( 'last_run_test' )
assert_equal( true, result, "check 2" )
result = Sessions::CacheIn.get( 'last_run_test' )
assert_equal( nil, result, "check 2" )
# check delete cache
Sessions::CacheIn.set( 'last_run_delete' , true, { :expires_in => 5.seconds } )
result = Sessions::CacheIn.get( 'last_run_delete' )
assert_equal( true, result, "check 1" )
Sessions::CacheIn.delete( 'last_run_delete' )
result = Sessions::CacheIn.get( 'last_run_delete' )
assert_equal( nil, nil, "check delete" )
end
test 'b collections group' do
require 'sessions/backend/collections/group.rb'
user = User.lookup(:id => 1)
collection_client1 = Sessions::Backend::Collections::Group.new(user, false, '123-1')
collection_client2 = Sessions::Backend::Collections::Group.new(user, false, '234-2')
# get whole collections
result1 = collection_client1.push
assert( !result1.empty?, "check collections" )
sleep 1
result2 = collection_client2.push
assert( !result2.empty?, "check collections" )
assert_equal( result1, result2, "check collections" )
# next check should be empty
result1 = collection_client1.push
assert( !result1, "check collections - recall" )
sleep 1
result2 = collection_client2.push
assert( !result2, "check collections - recall" )
# change collection
group = Group.first
group.touch
sleep 16
# get whole collections
result1 = collection_client1.push
assert( !result1.empty?, "check collections - after touch" )
sleep 1
result2 = collection_client2.push
assert( !result2.empty?, "check collections - after touch" )
assert_equal( result1, result2, "check collections" )
# check again after touch
result1 = collection_client1.push
assert( !result1, "check collections - after touch - recall" )
sleep 1
result2 = collection_client2.push
assert( !result2, "check collections - after touch - recall" )
assert_equal( result1, result2, "check collections" )
# change collection
group = Group.create( :name => 'SomeGroup::' + rand(999999).to_s, :active => true, :created_by_id => 1, :updated_by_id => 1 )
sleep 12
# get whole collections
result1 = collection_client1.push
assert( !result1.empty?, "check collections - after create" )
sleep 1
result2 = collection_client2.push
assert( !result2.empty?, "check collections - after create" )
assert_equal( result1, result2, "check collections" )
# check again after create
sleep 14
result1 = collection_client1.push
assert( !result1, "check collections - after create - recall" )
sleep 1
result2 = collection_client2.push
assert( !result2, "check collections - after create - recall" )
assert_equal( result1, result2, "check collections" )
# change collection
group.destroy
sleep 14
# get whole collections
result1 = collection_client1.push
assert( !result1.empty?, "check collections - after destroy" )
sleep 1
result2 = collection_client2.push
assert( !result2.empty?, "check collections - after destroy" )
assert_equal( result1, result2, "check collections" )
# check again after destroy
sleep 12
result1 = collection_client1.push
assert( !result1, "check collections - after destroy - recall" )
sleep 1
result2 = collection_client2.push
assert( !result2, "check collections - after destroy - recall" )
assert_equal( result1, result2, "check collections" )
end
user = User.lookup(:id => 1)
roles = Role.where( :name => [ 'Agent', 'Admin'] )
user.roles = roles
user.save
test 'b collections organization' do
require 'sessions/backend/collections/organization.rb'
Organization.destroy_all
user = User.lookup(:id => 1)
collection_client1 = Sessions::Backend::Collections::Organization.new(user, false, '123-1')
collection_client2 = Sessions::Backend::Collections::Organization.new(user, false, '234-2')
# get whole collections - should be nil, no org exists!
result1 = collection_client1.push
assert( !result1, "check collections" )
sleep 1
result2 = collection_client2.push
assert( !result2, "check collections" )
assert_equal( result1, result2, "check collections" )
# next check - should still be nil, no org exists!
result1 = collection_client1.push
assert( !result1, "check collections - recall" )
sleep 1
result2 = collection_client2.push
assert( !result2, "check collections - recall" )
# change collection
org = Organization.create( :name => 'SomeOrg::' + rand(999999).to_s, :active => true, :created_by_id => 1, :updated_by_id => 1 )
sleep 16
# get whole collections
result1 = collection_client1.push
assert( !result1.empty?, "check collections - after create" )
sleep 1
result2 = collection_client2.push
assert( !result2.empty?, "check collections - after create" )
assert_equal( result1, result2, "check collections" )
sleep 16
# next check should be empty
result1 = collection_client1.push
assert( !result1, "check collections - after create recall" )
result2 = collection_client2.push
assert( !result2, "check collections - after create recall" )
organization = Organization.first
organization.touch
sleep 16
# get whole collections
result1 = collection_client1.push
assert( !result1.empty?, "check collections - after touch" )
result2 = collection_client2.push
assert( !result1.empty?, "check collections - after touch" )
assert_equal( result1, result2, "check collections" )
end
test 'b rss' do
user = User.lookup(:id => 1)
collection_client1 = Sessions::Backend::Rss.new(user, false, '123-1')
# get whole collections
result1 = collection_client1.push
#puts "RSS1: #{result1.inspect}"
assert( !result1.empty?, "check rss" )
sleep 1
# next check should be empty
result1 = collection_client1.push
#puts "R1: #{result1.inspect}"
assert( !result1, "check rss - recall" )
end
test 'b activity stream' do
# create users
roles = Role.where( :name => [ 'Agent', 'Admin'] )
groups = Group.all
UserInfo.current_user_id = 1
agent1 = User.create_or_update(
:login => 'activity-stream-agent-1',
:firstname => 'Session',
:lastname => 'activity stream ' + rand(99999).to_s,
:email => 'activity-stream-agent1@example.com',
:password => 'agentpw',
:active => true,
:roles => roles,
:groups => groups,
)
agent1.roles = roles
agent1.save
as_client1 = Sessions::Backend::ActivityStream.new(agent1, false, '123-1')
# get as stream
result1 = as_client1.push
assert( result1, "check as" )
sleep 1
# next check should be empty
result1 = as_client1.push
assert( !result1, "check as - recall" )
# next check should be empty
sleep 60
result1 = as_client1.push
assert( !result1, "check as - recall 2" )
agent1.update_attribute( :email, 'activity-stream-agent11@example.com' )
ticket = Ticket.create(:title => '12323', :updated_by_id => 1, :created_by_id => 1, :group_id => 1, :priority_id => 1, :state_id => 1, :customer_id => 1)
sleep 32
# get as stream
result1 = as_client1.push
assert( result1, "check as - recall 3" )
end
test 'b recent_viewed' do
user = User.lookup(:id => 1)
ticket = Ticket.find(1)
RecentView.log( ticket, user )
recent_viewed_client1 = Sessions::Backend::RecentViewed.new(user, false, '123-1')
# get as stream
result1 = recent_viewed_client1.push
assert( result1, "check recent_viewed" )
sleep 1
# next check should be empty
result1 = recent_viewed_client1.push
assert( !result1, "check recent_viewed - recall" )
# next check should be empty
sleep 20
result1 = recent_viewed_client1.push
assert( !result1, "check recent_viewed - recall 2" )
RecentView.log( ticket, user )
sleep 20
# get as stream
result1 = recent_viewed_client1.push
assert( result1, "check recent_viewed - recall 3" )
end
test 'b ticket_create' do
user = User.lookup(:id => 1)
ticket_create_client1 = Sessions::Backend::TicketCreate.new(user, false, '123-1')
# get as stream
result1 = ticket_create_client1.push
assert( result1, "check ticket_create" )
sleep 1
# next check should be empty
result1 = ticket_create_client1.push
assert( !result1, "check ticket_create - recall" )
# next check should be empty
sleep 10
result1 = ticket_create_client1.push
assert( !result1, "check ticket_create - recall 2" )
Group.create( :name => 'SomeTicketCreateGroup::' + rand(999999).to_s, :active => true, :created_by_id => 1, :updated_by_id => 1 )
sleep 26
# get as stream
result1 = ticket_create_client1.push
assert( result1, "check ticket_create - recall 3" )
end
test 'b ticket_overview_index' do
user = User.lookup(:id => 1)
ticket_overview_index_client1 = Sessions::Backend::TicketOverviewIndex.new(user, false, '123-1')
# get as stream
result1 = ticket_overview_index_client1.push
assert( result1, "check ticket_overview_index" )
sleep 1
# next check should be empty
result1 = ticket_overview_index_client1.push
assert( !result1, "check ticket_overview_index - recall" )
# next check should be empty
sleep 10
result1 = ticket_overview_index_client1.push
assert( !result1, "check ticket_overview_index - recall 2" )
ticket = Ticket.create( :title => '12323', :updated_by_id => 1, :created_by_id => 1, :group_id => 1, :priority_id => 1, :state_id => 1, :customer_id => 1)
sleep 10
# get as stream
result1 = ticket_overview_index_client1.push
assert( result1, "check ticket_overview_index - recall 3" )
end
end

View file

@ -0,0 +1,147 @@
# encoding: utf-8
require 'test_helper'
class SessionCollectionsTest < ActiveSupport::TestCase
test 'c collections' do
UserInfo.current_user_id = 1
# create users
roles = Role.where( :name => [ 'Agent', 'Admin'] )
groups = Group.all
agent1 = User.create_or_update(
:login => 'session-collections-agent-1',
:firstname => 'Session',
:lastname => 'collections 1',
:email => 'session-collections-agent-1@example.com',
:password => 'agentpw',
:active => true,
:roles => roles,
:groups => groups,
)
agent1.roles = roles
agent1.save
roles = Role.where( :name => [ 'Agent' ] )
groups = Group.all
agent2 = User.create_or_update(
:login => 'session-collections-agent-2',
:firstname => 'Session',
:lastname => 'collections 2',
:email => 'session-collections-agent-2@example.com',
:password => 'agentpw',
:active => true,
:roles => roles,
:groups => groups,
)
agent2.roles = roles
agent2.save
roles = Role.where( :name => [ 'Customer'] )
customer1 = User.create_or_update(
:login => 'session-collections-customer-1',
:firstname => 'Session',
:lastname => 'collections 2',
:email => 'session-collections-customer-1@example.com',
:password => 'customerpw',
:active => true,
:roles => roles,
)
customer1.roles = roles
customer1.save
collection_client1 = Sessions::Backend::Collections.new(agent1, nil, 'aaa-1')
collection_client2 = Sessions::Backend::Collections.new(agent2, nil, 'bbb-2')
collection_client3 = Sessions::Backend::Collections.new(customer1, nil, 'bbb-2')
# get whole collections
result1 = collection_client1.push
assert( result1, "check collections" )
assert( check_if_collection_exists(result1, :Group), "check collections - after init" )
assert( check_if_collection_exists(result1, :Role), "check collections - after init" )
assert( check_if_collection_exists(result1, :Signature), "check collections - after init" )
assert( check_if_collection_exists(result1, :EmailAddress), "check collections - after init" )
sleep 1
result2 = collection_client2.push
assert( result2, "check collections" )
assert( check_if_collection_exists(result2, :Group), "check collections - after init" )
assert( check_if_collection_exists(result2, :Role), "check collections - after init" )
assert( check_if_collection_exists(result2, :Signature), "check collections - after init" )
assert( check_if_collection_exists(result2, :EmailAddress), "check collections - after init" )
assert_equal( result1, result2, "check collections" )
result3 = collection_client3.push
assert( result3, "check collections" )
assert( check_if_collection_exists(result3, :Group), "check collections - after init" )
assert( check_if_collection_exists(result3, :Role), "check collections - after init" )
assert( !check_if_collection_exists(result3, :Signature), "check collections - after init" )
assert( !check_if_collection_exists(result3, :EmailAddress), "check collections - after init" )
# next check should be empty
result1 = collection_client1.push
assert( result1.empty?, "check collections - recall" )
sleep 1
result2 = collection_client2.push
assert( result2.empty?, "check collections - recall" )
sleep 0.2
result3 = collection_client3.push
assert( result3.empty?, "check collections - recall" )
# change collection
group = Group.first
group.touch
sleep 16
# get whole collections
result1 = collection_client1.push
assert( result1, "check collections - after touch" )
assert( check_if_collection_exists(result1, :Group), "check collections - after touch" )
sleep 1
result2 = collection_client2.push
assert( result2, "check collections - after touch" )
assert( check_if_collection_exists(result2, :Group), "check collections - after touch" )
sleep 0.2
result3 = collection_client3.push
assert( result3, "check collections - after touch" )
assert( check_if_collection_exists(result3, :Group), "check collections - after touch" )
# change collection
org = Organization.create( :name => 'SomeOrg::' + rand(999999).to_s, :active => true )
sleep 16
# get whole collections
result1 = collection_client1.push
assert( result1, "check collections - after create" )
assert( check_if_collection_exists(result1, :Organization), "check collections - after create" )
sleep 0.5
result2 = collection_client2.push
assert( result2, "check collections - after create" )
assert( check_if_collection_exists(result2, :Organization), "check collections - after create" )
sleep 0.5
result3 = collection_client3.push
assert( result3, "check collections - after create" )
assert( !check_if_collection_exists(result3, :Organization), "check collections - after create" )
# next check should be empty
sleep 16
result1 = collection_client1.push
assert( result1.empty?, "check collections - recall" )
sleep 1
result2 = collection_client2.push
assert( result2.empty?, "check collections - recall" )
sleep 0.2
result3 = collection_client3.push
assert( result3.empty?, "check collections - recall" )
end
def check_if_collection_exists(results, collection)
results.each {|result|
return true if result && result[:collection] && result[:collection][collection]
}
nil
end
end

View file

@ -1,70 +1,8 @@
# encoding: utf-8
require 'test_helper'
class SessionTest < ActiveSupport::TestCase
test 'a cache' do
Sessions::CacheIn.set( 'last_run_test' , true, { :expires_in => 2.seconds } )
result = Sessions::CacheIn.get( 'last_run_test' )
assert_equal( true, result, "check 1" )
# should not be expired
result = Sessions::CacheIn.expired( 'last_run_test' )
assert_equal( false, result, "check 1 - expired" )
# should be expired
sleep 3
result = Sessions::CacheIn.expired( 'last_run_test' )
assert_equal( true, result, "check 1 - expired" )
# renew expire
result = Sessions::CacheIn.get( 'last_run_test', :re_expire => true )
assert_equal( true, result, "check 1 - re_expire" )
# should not be expired
result = Sessions::CacheIn.expired( 'last_run_test' )
assert_equal( false, result, "check 1 - expired" )
# ignore expired
sleep 3
result = Sessions::CacheIn.get( 'last_run_test', :ignore_expire => true )
assert_equal( true, result, "check 1 - ignore_expire" )
# should be expired
result = Sessions::CacheIn.expired( 'last_run_test' )
assert_equal( true, result, "check 2" )
result = Sessions::CacheIn.get( 'last_run_test' )
assert_equal( nil, result, "check 2" )
end
test 'worker' do
# create users
roles = Role.where( :name => [ 'Agent'] )
groups = Group.all
UserInfo.current_user_id = 1
agent1 = User.create_or_update(
:login => 'session-agent-1',
:firstname => 'Session',
:lastname => 'Agent 1',
:email => 'session-agent1@example.com',
:password => 'agentpw',
:active => true,
:roles => roles,
:groups => groups,
)
worker = Thread.new {
Sessions.thread_worker(agent1.id)
}
#Sessions::Backend::TicketOverviewIndex.worker()
worker.exit
end
test 'z full' do
class SessionEnhancedTest < ActiveSupport::TestCase
test 'a check clients and send messages' do
# create users
roles = Role.where( :name => [ 'Agent'] )
@ -194,11 +132,6 @@ class SessionTest < ActiveSupport::TestCase
sleep 5
#jobs.join
# check worker threads
assert( Sessions.thread_worker_exists?(agent1), "check if worker is running" )
assert( Sessions.thread_worker_exists?(agent2), "check if worker is running" )
assert( Sessions.thread_worker_exists?(agent3), "check if worker is running" )
# check client threads
assert( Sessions.thread_client_exists?(client_id1), "check if client is running" )
assert( Sessions.thread_client_exists?(client_id2), "check if client is running" )
@ -220,13 +153,121 @@ class SessionTest < ActiveSupport::TestCase
assert( !Sessions.thread_client_exists?(client_id2), "check if client is running" )
assert( !Sessions.thread_client_exists?(client_id3), "check if client is running" )
# check worker threads
assert( !Sessions.thread_worker_exists?(agent1), "check if worker is running" )
assert( !Sessions.thread_worker_exists?(agent2), "check if worker is running" )
assert( !Sessions.thread_worker_exists?(agent3), "check if worker is running" )
# exit jobs
jobs.exit
end
test 'b check client and backends' do
# create users
roles = Role.where( :name => [ 'Agent'] )
groups = Group.all
UserInfo.current_user_id = 1
agent1 = User.create_or_update(
:login => 'session-agent-1',
:firstname => 'Session',
:lastname => 'Agent 1',
:email => 'session-agent1@example.com',
:password => 'agentpw',
:active => true,
:roles => roles,
:groups => groups,
)
agent2 = User.create_or_update(
:login => 'session-agent-2',
:firstname => 'Session',
:lastname => 'Agent 2',
:email => 'session-agent2@example.com',
:password => 'agentpw',
:active => true,
:roles => roles,
:groups => groups,
)
# create sessions
client_id1_0 = '1234-1'
client_id1_1 = '1234-2'
client_id2 = '123456'
Sessions.destory(client_id1_0)
Sessions.destory(client_id1_1)
Sessions.destory(client_id2)
# start jobs
jobs = Thread.new {
Sessions.jobs
}
sleep 5
Sessions.create( client_id1_0, agent1.attributes, { :type => 'websocket' } )
sleep 5.5
Sessions.create( client_id1_1, agent1.attributes, { :type => 'websocket' } )
sleep 1.2
Sessions.create( client_id2, agent2.attributes, { :type => 'ajax' } )
# check if session exists
assert( Sessions.session_exists?(client_id1_0), "check if session exists" )
assert( Sessions.session_exists?(client_id1_1), "check if session exists" )
assert( Sessions.session_exists?(client_id2), "check if session exists" )
sleep 19
# check collections
collections = {
'Group' => true,
'Organization' => true,
'User' => nil,
}
check_if_collection_reset_message_exists(client_id1_0, collections, 'init')
check_if_collection_reset_message_exists(client_id1_1, collections, 'init')
check_if_collection_reset_message_exists(client_id2, collections, 'init')
# change collection
group = Group.first
group.touch
sleep 20
# check collections
collections = {
'Group' => true,
'Organization' => nil,
'User' => nil,
}
check_if_collection_reset_message_exists(client_id1_0, collections, 'update')
check_if_collection_reset_message_exists(client_id1_1, collections, 'update')
check_if_collection_reset_message_exists(client_id2, collections, 'update')
# check if session still exists after idle cleanup
sleep 62
client_ids = Sessions.destory_idle_sessions(1)
# check client sessions
assert( !Sessions.session_exists?(client_id1_0), "check if session is removed" )
assert( !Sessions.session_exists?(client_id1_1), "check if session is removed" )
assert( !Sessions.session_exists?(client_id2), "check if session is removed" )
end
def check_if_collection_reset_message_exists(client_id, collections_orig, type)
messages = Sessions.queue(client_id)
puts "cid: #{client_id}"
#puts "m: #{messages.inspect}"
collections_result = {}
messages.each {|message|
#puts ""
#puts "message: #{message.inspect}"
if message['event'] == 'resetCollection'
puts "rc: "
if message['data']
message['data'].each {|key, value|
puts "rc: #{key}"
collections_result[key] = true
}
end
end
}
puts "c: #{collections_result.inspect}"
collections_orig.each {|key, value|
assert_equal( collections_orig[key], collections_result[key], "collection message for #{key} #{type}-check" )
}
end
end