whoisonline 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +307 -76
- data/lib/whoisonline/engine.rb +3 -0
- data/lib/whoisonline/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dcd954e1560a78b4047064f6b1359d22f159b08fd86f3c8cea97283f8a7f2210
|
|
4
|
+
data.tar.gz: '06558961aad1873ceb47cf7799049603a9994376a9a2a9ed0b54eeb43b688207'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 139becc8c6d5cdd18578023ba4a9c751a6f9803ec2396d73a229e6421d4b21543d3de4327b37513cc9075c3c5f9deb21d1f4e0900a03e84ac24db374d219af71
|
|
7
|
+
data.tar.gz: a2bd79ab7b77f9524865030f2af74cc011187191d1403968e094a26ed663866fa83d6e2a9a1a41512e3bfb805e2c7f61afa43a46e76dc98e2b7a6aede6b8096c
|
data/README.md
CHANGED
|
@@ -1,125 +1,356 @@
|
|
|
1
|
-
# WhoIsOnline
|
|
1
|
+
# WhoIsOnline 💚
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<div align="center">
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
- **Visible-only heartbeats**: only ping while the tab is visible/active (configurable interval).
|
|
11
|
-
- Throttled Redis writes to reduce load (configurable).
|
|
12
|
-
- Safe SCAN-based counting; no `KEYS`.
|
|
13
|
-
- Configurable Redis client, TTL, throttle duration, user id method, controller accessor, namespace, and heartbeat interval.
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
**Track "who is online right now?" in Rails using Redis TTL. Zero database writes, production-ready, and auto-hooks into controllers.**
|
|
12
|
+
|
|
13
|
+
[Installation](#-installation) • [Quick Start](#-quick-start) • [Configuration](#-configuration) • [API](#-public-api) • [Examples](#-examples)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## ✨ Features
|
|
20
|
+
|
|
21
|
+
- 🚀 **Zero Setup** - Rails Engine auto-includes controller concern
|
|
22
|
+
- 🔌 **Works with Any Auth** - Devise, custom, or any `current_user` method
|
|
23
|
+
- ⚡ **Redis TTL-Based** - No database tables required
|
|
24
|
+
- 👁️ **Smart Tracking** - Only tracks when tab is visible/active
|
|
25
|
+
- 🔄 **Automatic Offline Detection** - Marks users offline when browser closes
|
|
26
|
+
- ⏱️ **Throttled Writes** - Configurable to reduce Redis load
|
|
27
|
+
- 🔍 **SCAN-Based** - Safe counting without blocking Redis (`KEYS` not used)
|
|
28
|
+
- 🎛️ **Highly Configurable** - Redis client, TTL, throttle, heartbeat interval, and more
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 📦 Installation
|
|
33
|
+
|
|
34
|
+
### From RubyGems (Recommended)
|
|
35
|
+
|
|
36
|
+
Add to your `Gemfile`:
|
|
17
37
|
|
|
18
38
|
```ruby
|
|
19
|
-
gem "whoisonline"
|
|
39
|
+
gem "whoisonline"
|
|
20
40
|
```
|
|
21
41
|
|
|
22
|
-
|
|
42
|
+
Then run:
|
|
23
43
|
|
|
24
44
|
```bash
|
|
25
|
-
bundle
|
|
45
|
+
bundle install
|
|
26
46
|
```
|
|
27
47
|
|
|
28
|
-
|
|
29
|
-
|
|
48
|
+
### From GitHub (Development)
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
gem "whoisonline", github: "KapilDevPal/WhoIsOnline"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 🚀 Quick Start
|
|
57
|
+
|
|
58
|
+
### 1. Create Initializer
|
|
59
|
+
|
|
60
|
+
Create `config/initializers/whoisonline.rb`:
|
|
30
61
|
|
|
31
62
|
```ruby
|
|
32
63
|
WhoIsOnline.configure do |config|
|
|
33
64
|
config.redis = -> { Redis.new(url: ENV.fetch("REDIS_URL")) }
|
|
34
65
|
config.ttl = 5.minutes
|
|
35
66
|
config.throttle = 60.seconds
|
|
36
|
-
config.
|
|
37
|
-
config.heartbeat_interval = 60.seconds # client heartbeat when tab visible
|
|
67
|
+
config.heartbeat_interval = 60.seconds # Heartbeat when tab is visible
|
|
38
68
|
end
|
|
39
69
|
```
|
|
40
70
|
|
|
41
|
-
|
|
71
|
+
### 2. Add to Layout (Optional but Recommended)
|
|
42
72
|
|
|
43
|
-
|
|
73
|
+
Add to your main layout (`app/views/layouts/application.html.erb`):
|
|
44
74
|
|
|
45
75
|
```erb
|
|
46
|
-
|
|
76
|
+
<!DOCTYPE html>
|
|
77
|
+
<html>
|
|
78
|
+
<head>
|
|
79
|
+
<title>My App</title>
|
|
80
|
+
<%= csrf_meta_tags %>
|
|
81
|
+
</head>
|
|
82
|
+
<body>
|
|
83
|
+
<%= yield %>
|
|
84
|
+
<%= whoisonline_offline_script %>
|
|
85
|
+
</body>
|
|
86
|
+
</html>
|
|
47
87
|
```
|
|
48
88
|
|
|
49
|
-
|
|
50
|
-
|
|
89
|
+
**That's it!** The engine automatically tracks users online after each controller action.
|
|
90
|
+
|
|
91
|
+
---
|
|
51
92
|
|
|
52
|
-
## Public API
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
93
|
+
## 📖 Public API
|
|
94
|
+
|
|
95
|
+
```ruby
|
|
96
|
+
# Mark user online (auto-called by controller concern)
|
|
97
|
+
WhoIsOnline.track(user)
|
|
98
|
+
|
|
99
|
+
# Mark user offline immediately
|
|
100
|
+
WhoIsOnline.offline(user)
|
|
101
|
+
|
|
102
|
+
# Check if user is online
|
|
103
|
+
WhoIsOnline.online?(user) # => true/false
|
|
104
|
+
|
|
105
|
+
# Get count of online users
|
|
106
|
+
WhoIsOnline.count # => 42
|
|
107
|
+
|
|
108
|
+
# Get array of online user IDs
|
|
109
|
+
WhoIsOnline.user_ids # => ["1", "2", "3"]
|
|
110
|
+
|
|
111
|
+
# Get ActiveRecord relation of online users
|
|
112
|
+
WhoIsOnline.users(User) # => User.where(id: [...])
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## ⚙️ Configuration
|
|
59
118
|
|
|
60
|
-
## Configuration
|
|
61
119
|
```ruby
|
|
62
120
|
WhoIsOnline.configure do |config|
|
|
121
|
+
# Redis connection (required)
|
|
63
122
|
config.redis = -> { Redis.new(url: ENV.fetch("REDIS_URL", "redis://127.0.0.1:6379/0")) }
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
config.
|
|
67
|
-
config.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
config.
|
|
71
|
-
config.
|
|
123
|
+
|
|
124
|
+
# TTL settings
|
|
125
|
+
config.ttl = 5.minutes # How long user stays online without activity
|
|
126
|
+
config.throttle = 60.seconds # Minimum time between Redis writes per user
|
|
127
|
+
|
|
128
|
+
# User identification
|
|
129
|
+
config.user_id_method = :id # Method to get user ID
|
|
130
|
+
config.current_user_method = :current_user # Method on controllers to get user
|
|
131
|
+
|
|
132
|
+
# Heartbeat (for visible tab tracking)
|
|
133
|
+
config.heartbeat_interval = 60.seconds # Heartbeat frequency when tab is visible
|
|
134
|
+
|
|
135
|
+
# Advanced
|
|
136
|
+
config.namespace = "whoisonline:user" # Redis key namespace
|
|
137
|
+
config.auto_hook = true # Auto-include controller concern
|
|
138
|
+
config.logger = Rails.logger # Logger instance
|
|
139
|
+
end
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Configuration Options
|
|
143
|
+
|
|
144
|
+
| Option | Default | Description |
|
|
145
|
+
|--------|---------|-------------|
|
|
146
|
+
| `ttl` | `5.minutes` | How long a user stays online without activity |
|
|
147
|
+
| `throttle` | `60.seconds` | Minimum time between Redis writes per user |
|
|
148
|
+
| `heartbeat_interval` | `60.seconds` | Heartbeat frequency when tab is visible |
|
|
149
|
+
| `user_id_method` | `:id` | Method to extract ID from user object |
|
|
150
|
+
| `current_user_method` | `:current_user` | Method name on controllers |
|
|
151
|
+
| `namespace` | `"whoisonline:user"` | Redis key namespace prefix |
|
|
152
|
+
| `auto_hook` | `true` | Auto-include controller concern |
|
|
153
|
+
| `logger` | `Rails.logger` | Logger for errors/warnings |
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## 💡 Examples
|
|
158
|
+
|
|
159
|
+
### Basic Usage
|
|
160
|
+
|
|
161
|
+
```ruby
|
|
162
|
+
# In a controller (automatic via engine)
|
|
163
|
+
# Users are tracked after each action
|
|
164
|
+
|
|
165
|
+
# Check if user is online
|
|
166
|
+
if WhoIsOnline.online?(current_user)
|
|
167
|
+
# User is currently online
|
|
72
168
|
end
|
|
169
|
+
|
|
170
|
+
# Get online users count
|
|
171
|
+
@online_count = WhoIsOnline.count
|
|
172
|
+
|
|
173
|
+
# Get online users
|
|
174
|
+
@online_users = WhoIsOnline.users(User)
|
|
73
175
|
```
|
|
74
176
|
|
|
75
|
-
|
|
76
|
-
- Uses `SET key value EX ttl` for O(1) writes.
|
|
77
|
-
- Throttling prevents hot users from spamming Redis.
|
|
78
|
-
- Counting and user listing use `SCAN` to avoid blocking Redis (`KEYS` is not used).
|
|
79
|
-
- Namespace keeps presence keys isolated; use a dedicated Redis db/cluster for large scale.
|
|
177
|
+
### Manual Tracking
|
|
80
178
|
|
|
81
|
-
## Example Usage in Rails
|
|
82
179
|
```ruby
|
|
83
|
-
#
|
|
180
|
+
# Manually mark user online
|
|
84
181
|
WhoIsOnline.track(current_user)
|
|
85
182
|
|
|
86
|
-
#
|
|
183
|
+
# Manually mark user offline (e.g., on logout)
|
|
87
184
|
WhoIsOnline.offline(current_user)
|
|
185
|
+
```
|
|
88
186
|
|
|
89
|
-
|
|
90
|
-
if WhoIsOnline.online?(user)
|
|
91
|
-
# notify
|
|
92
|
-
end
|
|
187
|
+
### In Background Jobs
|
|
93
188
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
189
|
+
```ruby
|
|
190
|
+
class NotificationJob < ApplicationJob
|
|
191
|
+
def perform(user_id)
|
|
192
|
+
user = User.find(user_id)
|
|
193
|
+
|
|
194
|
+
if WhoIsOnline.online?(user)
|
|
195
|
+
# Only notify if user is online
|
|
196
|
+
NotificationService.deliver(user)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
97
200
|
```
|
|
98
201
|
|
|
99
|
-
###
|
|
100
|
-
|
|
202
|
+
### Dashboard View
|
|
203
|
+
|
|
204
|
+
```ruby
|
|
205
|
+
# In your controller
|
|
206
|
+
class DashboardController < ApplicationController
|
|
207
|
+
def index
|
|
208
|
+
@online_count = WhoIsOnline.count
|
|
209
|
+
@online_users = WhoIsOnline.users(User)
|
|
210
|
+
.order(last_sign_in_at: :desc)
|
|
211
|
+
.limit(50)
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
```
|
|
101
215
|
|
|
102
216
|
```erb
|
|
103
|
-
|
|
104
|
-
<
|
|
105
|
-
<
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
217
|
+
<!-- In your view -->
|
|
218
|
+
<div class="online-users">
|
|
219
|
+
<h2>Online Now (<%= @online_count %>)</h2>
|
|
220
|
+
<ul>
|
|
221
|
+
<% @online_users.each do |user| %>
|
|
222
|
+
<li><%= user.name %> <span class="badge">●</span></li>
|
|
223
|
+
<% end %>
|
|
224
|
+
</ul>
|
|
225
|
+
</div>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 🎯 How It Works
|
|
231
|
+
|
|
232
|
+
1. **Controller Action** - After each action, the engine automatically calls `WhoIsOnline.track(current_user)`
|
|
233
|
+
2. **Redis Write** - User presence is stored in Redis with TTL: `SET whoisonline:user:123 <timestamp> EX 300`
|
|
234
|
+
3. **Throttling** - Writes are throttled per user to prevent Redis spam
|
|
235
|
+
4. **Heartbeat** - When tab is visible, JavaScript sends periodic heartbeats to keep user online
|
|
236
|
+
5. **Offline Detection** - When browser closes, JavaScript sends offline request
|
|
237
|
+
6. **TTL Expiry** - If no activity, Redis key expires automatically
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## ⚡ Performance
|
|
242
|
+
|
|
243
|
+
- **O(1) Writes** - Uses `SET key value EX ttl` for constant-time operations
|
|
244
|
+
- **Throttled** - Prevents hot users from spamming Redis
|
|
245
|
+
- **SCAN-Based** - Counting uses `SCAN` instead of `KEYS` (non-blocking)
|
|
246
|
+
- **Namespace Isolation** - Keys are namespaced for easy management
|
|
247
|
+
- **No Database** - Zero database writes, all in Redis
|
|
248
|
+
|
|
249
|
+
### Recommended Settings
|
|
250
|
+
|
|
251
|
+
For **high-traffic** applications:
|
|
252
|
+
|
|
253
|
+
```ruby
|
|
254
|
+
config.ttl = 2.minutes # Shorter TTL = more accurate
|
|
255
|
+
config.throttle = 30.seconds # More frequent updates
|
|
256
|
+
config.heartbeat_interval = 30.seconds # More frequent heartbeats
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
For **low-traffic** applications:
|
|
260
|
+
|
|
261
|
+
```ruby
|
|
262
|
+
config.ttl = 10.minutes # Longer TTL = less Redis activity
|
|
263
|
+
config.throttle = 120.seconds # Less frequent updates
|
|
264
|
+
config.heartbeat_interval = 120.seconds # Less frequent heartbeats
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## 🔧 Troubleshooting
|
|
270
|
+
|
|
271
|
+
### Users Not Showing as Online
|
|
272
|
+
|
|
273
|
+
1. Check Redis connection: `redis-cli ping`
|
|
274
|
+
2. Verify `current_user` method exists in your controllers
|
|
275
|
+
3. Check logs for errors: `tail -f log/development.log`
|
|
276
|
+
4. Verify TTL hasn't expired: `redis-cli TTL whoisonline:user:1`
|
|
277
|
+
|
|
278
|
+
### Helper Not Available
|
|
279
|
+
|
|
280
|
+
If `whoisonline_offline_script` is not available:
|
|
281
|
+
|
|
282
|
+
1. Restart Rails server
|
|
283
|
+
2. Check that gem is loaded: `bundle list | grep whoisonline`
|
|
284
|
+
3. Verify engine is loaded: Check `config/application.rb` for engine loading
|
|
285
|
+
|
|
286
|
+
### Heartbeat Not Working
|
|
287
|
+
|
|
288
|
+
1. Check browser console for JavaScript errors
|
|
289
|
+
2. Verify CSRF token is present: `<%= csrf_meta_tags %>`
|
|
290
|
+
3. Check network tab for heartbeat requests
|
|
291
|
+
4. Verify `heartbeat_interval` is configured
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## 🛠️ Extensibility
|
|
296
|
+
|
|
297
|
+
The gem is designed to be extensible:
|
|
298
|
+
|
|
299
|
+
- **ActionCable Integration** - Broadcast presence changes
|
|
300
|
+
- **Custom Events** - Hook into track/offline events
|
|
301
|
+
- **Multiple Redis Instances** - Use different Redis for presence
|
|
302
|
+
- **Custom User Models** - Works with any user model structure
|
|
303
|
+
|
|
304
|
+
Example: ActionCable Integration
|
|
305
|
+
|
|
306
|
+
```ruby
|
|
307
|
+
# In an initializer
|
|
308
|
+
WhoIsOnline.tracker.define_singleton_method(:track) do |user|
|
|
309
|
+
super(user)
|
|
310
|
+
ActionCable.server.broadcast("presence", { user_id: user.id, status: "online" })
|
|
311
|
+
end
|
|
114
312
|
```
|
|
115
313
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## 📝 License
|
|
317
|
+
|
|
318
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## 👤 Author
|
|
323
|
+
|
|
324
|
+
**Kapil Dev Pal**
|
|
325
|
+
|
|
326
|
+
- 📧 Email: dev.kapildevpal@gmail.com
|
|
327
|
+
- 🐦 Twitter: [@rails_to_rescue](https://twitter.com/rails_to_rescue)
|
|
328
|
+
- 🚀 Project: [rails_to_rescue](https://github.com/rails-to-rescue)
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## 🤝 Contributing
|
|
333
|
+
|
|
334
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
335
|
+
|
|
336
|
+
1. Fork the repository
|
|
337
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
338
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
339
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
340
|
+
5. Open a Pull Request
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## ⭐ Show Your Support
|
|
345
|
+
|
|
346
|
+
If you find this gem useful, please give it a ⭐ on GitHub!
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
<div align="center">
|
|
120
351
|
|
|
121
|
-
|
|
122
|
-
- Kapil Dev Pal – dev.kapildevpal@gmail.com / @rails_to_rescue
|
|
123
|
-
- Project: rails_to_rescue
|
|
352
|
+
**Made with ❤️ for the Rails community**
|
|
124
353
|
|
|
354
|
+
[Report Bug](https://github.com/KapilDevPal/WhoIsOnline/issues) • [Request Feature](https://github.com/KapilDevPal/WhoIsOnline/issues) • [View on GitHub](https://github.com/KapilDevPal/WhoIsOnline)
|
|
125
355
|
|
|
356
|
+
</div>
|
data/lib/whoisonline/engine.rb
CHANGED
|
@@ -21,6 +21,9 @@ module WhoIsOnline
|
|
|
21
21
|
|
|
22
22
|
initializer "whoisonline.helpers" do
|
|
23
23
|
ActiveSupport.on_load(:action_view) do
|
|
24
|
+
# Explicitly require the helper module from app directory
|
|
25
|
+
helper_path = File.join(Engine.root, "app", "helpers", "whoisonline", "application_helper.rb")
|
|
26
|
+
require helper_path if File.exist?(helper_path)
|
|
24
27
|
include WhoIsOnline::ApplicationHelper
|
|
25
28
|
end
|
|
26
29
|
end
|
data/lib/whoisonline/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: whoisonline
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kapil Dev Pal
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-12-
|
|
11
|
+
date: 2025-12-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|