blob: 854ce5957f7c97c22ac48cb761d439f40af5814d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe AwarenessSession, :clean_gitlab_redis_shared_state do
subject { AwarenessSession.for(session_id) }
let!(:user) { create(:user) }
let(:session_id) { 1 }
describe "when initiating a session" do
it "provides a string representation of the model instance" do
expected = "awareness_session=6b86b273ff34fce"
expect(subject.to_s).to eql(expected)
end
it "provides a parameterized version of the session identifier" do
expected = "6b86b273ff34fce"
expect(subject.to_param).to eql(expected)
end
end
describe "when a user joins a session" do
let(:user2) { create(:user) }
let(:presence_ttl) { 15.minutes }
it "changes number of session members" do
expect { subject.join(user) }.to change(subject, :size).by(1)
end
it "returns user as member of session with last_activity timestamp" do
freeze_time do
subject.join(user)
session_users = subject.users_with_last_activity
session_user, last_activity = session_users.first
expect(session_user.id).to be(user.id)
expect(last_activity).to be_eql(Time.now.utc)
end
end
it "maintains user ID and last_activity pairs" do
now = Time.zone.now
travel_to now - 1.minute do
subject.join(user2)
end
travel_to now do
subject.join(user)
end
session_users = subject.users_with_last_activity
expect(session_users[0].first.id).to eql(user.id)
expect(session_users[0].last.to_i).to eql(now.to_i)
expect(session_users[1].first.id).to eql(user2.id)
expect(session_users[1].last.to_i).to eql((now - 1.minute).to_i)
end
it "reports user as present" do
freeze_time do
subject.join(user)
expect(subject.present?(user, threshold: presence_ttl)).to be true
end
end
it "reports user as away after a certain time on inactivity" do
subject.join(user)
travel_to((presence_ttl + 1.minute).from_now) do
expect(subject.away?(user, threshold: presence_ttl)).to be true
end
end
it "reports user as present still when there was some activity" do
subject.join(user)
travel_to((presence_ttl - 1.minute).from_now) do
subject.touch!(user)
end
travel_to((presence_ttl + 1.minute).from_now) do
expect(subject.present?(user, threshold: presence_ttl)).to be true
end
end
it "creates user and session awareness keys in store" do
subject.join(user)
Gitlab::Redis::SharedState.with do |redis|
keys = redis.scan_each(match: "gitlab:awareness:*").to_a
expect(keys.size).to be(2)
end
end
it "sets a timeout for user and session key" do
subject.join(user)
subject_id = Digest::SHA256.hexdigest(session_id.to_s)[0, 15]
Gitlab::Redis::SharedState.with do |redis|
ttl_session = redis.ttl("gitlab:awareness:session:#{subject_id}:users")
ttl_user = redis.ttl("gitlab:awareness:user:#{user.id}:sessions")
expect(ttl_session).to be > 0
expect(ttl_user).to be > 0
end
end
it "fetches user(s) from database" do
subject.join(user)
expect(subject.users.first).to eql(user)
end
it "fetches and filters online user(s) from database" do
subject.join(user)
travel 2.hours do
subject.join(user2)
online_users = subject.online_users_with_last_activity
online_user, _ = online_users.first
expect(online_users.size).to be 1
expect(online_user).to eql(user2)
end
end
end
describe "when a user leaves a session" do
it "changes number of session members" do
subject.join(user)
expect { subject.leave(user) }.to change(subject, :size).by(-1)
end
it "destroys the session when it was the last user" do
subject.join(user)
expect { subject.leave(user) }.to change(subject, :id).to(nil)
end
end
describe "when last user leaves a session" do
it "session and user keys are removed" do
subject.join(user)
Gitlab::Redis::SharedState.with do |redis|
expect { subject.leave(user) }
.to change { redis.scan_each(match: "gitlab:awareness:*").to_a.size }
.to(0)
end
end
end
end
|