@@ -2,87 +2,77 @@ use std::collections::HashSet;
2
2
3
3
use redis_kiss:: { get_connection, AsyncCommands } ;
4
4
5
+ use rand:: Rng ;
5
6
mod entry;
6
7
mod operations;
7
8
8
- use entry:: { PresenceEntry , PresenceOp } ;
9
9
use operations:: {
10
- __add_to_set_sessions , __delete_key_presence_entry , __get_key_presence_entry ,
11
- __get_set_sessions , __remove_from_set_sessions , __set_key_presence_entry ,
10
+ __add_to_set_string , __add_to_set_u32 , __delete_key , __get_set_members_as_string ,
11
+ __get_set_size , __remove_from_set_string , __remove_from_set_u32 ,
12
12
} ;
13
13
14
- use crate :: presence:: operations:: __delete_set_sessions;
15
-
16
14
use self :: entry:: REGION_KEY ;
17
15
18
16
/// Create a new presence session, returns the ID of this session
19
- pub async fn presence_create_session ( user_id : & str , flags : u8 ) -> ( bool , u8 ) {
17
+ pub async fn presence_create_session ( user_id : & str , flags : u8 ) -> ( bool , u32 ) {
20
18
info ! ( "Creating a presence session for {user_id} with flags {flags}" ) ;
21
19
22
- // Try to find the presence entry for this user.
23
- let mut conn = get_connection ( ) . await . unwrap ( ) ;
24
- let mut entry: Vec < PresenceEntry > = __get_key_presence_entry ( & mut conn, user_id)
25
- . await
26
- . unwrap_or_default ( ) ;
20
+ if let Ok ( mut conn) = get_connection ( ) . await {
21
+ // Check whether this is the first session
22
+ let was_empty = __get_set_size ( & mut conn, user_id) . await == 0 ;
27
23
28
- // Return whether this was the first session.
29
- let was_empty = entry. is_empty ( ) ;
30
- info ! ( "User ID {} just came online." , & user_id) ;
24
+ // A session ID is comprised of random data and any flags ORed to the end
25
+ let session_id = {
26
+ let mut rng = rand:: thread_rng ( ) ;
27
+ ( rng. gen :: < u32 > ( ) ^ 1 ) | ( flags as u32 & 1 )
28
+ } ;
31
29
32
- // Generate session ID and push new entry.
33
- let session_id = entry . find_next_id ( ) ;
34
- entry . push ( PresenceEntry :: from ( session_id , flags ) ) ;
35
- __set_key_presence_entry ( & mut conn , user_id, entry ) . await ;
30
+ // Add session to user's sessions and to the region
31
+ __add_to_set_u32 ( & mut conn , user_id , session_id ) . await ;
32
+ __add_to_set_string ( & mut conn , & REGION_KEY , & format ! ( "{user_id}:{session_id}" ) ) . await ;
33
+ info ! ( "Created session for { user_id}, assigned them a session ID of {session_id}." ) ;
36
34
37
- // Add to region set in case of failure.
38
- __add_to_set_sessions ( & mut conn, & REGION_KEY , user_id, session_id) . await ;
39
- ( was_empty, session_id)
35
+ ( was_empty, session_id)
36
+ } else {
37
+ // Fail through
38
+ ( false , 0 )
39
+ }
40
40
}
41
41
42
42
/// Delete existing presence session
43
- pub async fn presence_delete_session ( user_id : & str , session_id : u8 ) -> bool {
43
+ pub async fn presence_delete_session ( user_id : & str , session_id : u32 ) -> bool {
44
44
presence_delete_session_internal ( user_id, session_id, false ) . await
45
45
}
46
46
47
47
/// Delete existing presence session (but also choose whether to skip region)
48
48
async fn presence_delete_session_internal (
49
49
user_id : & str ,
50
- session_id : u8 ,
50
+ session_id : u32 ,
51
51
skip_region : bool ,
52
52
) -> bool {
53
53
info ! ( "Deleting presence session for {user_id} with id {session_id}" ) ;
54
54
55
- // Return whether this was the last session.
56
- let mut is_empty = false ;
57
-
58
- // Only continue if we can actually find one.
59
- let mut conn = get_connection ( ) . await . unwrap ( ) ;
60
- let entry: Option < Vec < PresenceEntry > > = __get_key_presence_entry ( & mut conn, user_id) . await ;
61
- if let Some ( entry) = entry {
62
- let entries = entry
63
- . into_iter ( )
64
- . filter ( |x| x. session_id != session_id)
65
- . collect :: < Vec < PresenceEntry > > ( ) ;
66
-
67
- // If entry is empty, then just delete it.
68
- if entries. is_empty ( ) {
69
- __delete_key_presence_entry ( & mut conn, user_id) . await ;
70
- is_empty = true ;
71
- } else {
72
- __set_key_presence_entry ( & mut conn, user_id, entries) . await ;
73
- }
55
+ if let Ok ( mut conn) = get_connection ( ) . await {
56
+ // Remove the session
57
+ __remove_from_set_u32 ( & mut conn, user_id, session_id) . await ;
74
58
75
- // Remove from region set.
59
+ // Remove from the region
76
60
if !skip_region {
77
- __remove_from_set_sessions ( & mut conn, & REGION_KEY , user_id, session_id) . await ;
61
+ __remove_from_set_string ( & mut conn, & REGION_KEY , & format ! ( "{user_id}:{session_id}" ) )
62
+ . await ;
78
63
}
79
- }
80
64
81
- if is_empty {
82
- info ! ( "User ID {} just went offline." , & user_id) ;
83
- }
65
+ // Return whether this was the last session
66
+ let is_empty = __get_set_size ( & mut conn, user_id) . await == 0 ;
67
+ if is_empty {
68
+ info ! ( "User ID {} just went offline." , & user_id) ;
69
+ }
84
70
85
- is_empty
71
+ is_empty
72
+ } else {
73
+ // Fail through
74
+ false
75
+ }
86
76
}
87
77
88
78
/// Check whether a given user ID is online
@@ -102,6 +92,10 @@ pub async fn presence_filter_online(user_ids: &'_ [String]) -> HashSet<String> {
102
92
return set;
103
93
}
104
94
95
+ // NOTE: at the point that we need mobile indicators
96
+ // you can interpret the data here and return a new data
97
+ // structure like HashMap<String /* id */, u8 /* flags */>
98
+
105
99
// We need to handle a special case where only one is present
106
100
// as for some reason or another, Redis does not like us sending
107
101
// a list of just one ID to the server.
@@ -136,7 +130,7 @@ pub async fn presence_clear_region(region_id: Option<&str>) {
136
130
let region_id = region_id. unwrap_or ( & * REGION_KEY ) ;
137
131
let mut conn = get_connection ( ) . await . expect ( "Redis connection" ) ;
138
132
139
- let sessions = __get_set_sessions ( & mut conn, region_id) . await ;
133
+ let sessions = __get_set_members_as_string ( & mut conn, region_id) . await ;
140
134
if !sessions. is_empty ( ) {
141
135
info ! (
142
136
"Cleaning up {} sessions, this may take a while..." ,
@@ -155,7 +149,7 @@ pub async fn presence_clear_region(region_id: Option<&str>) {
155
149
}
156
150
157
151
// Then clear the set in Redis.
158
- __delete_set_sessions ( & mut conn, region_id) . await ;
152
+ __delete_key ( & mut conn, region_id) . await ;
159
153
160
154
info ! ( "Clean up complete." ) ;
161
155
}
0 commit comments