-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Sample that shows how effectively detect user presence (#39)
- Loading branch information
1 parent
5aafa76
commit 56a6864
Showing
34 changed files
with
1,125 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Presence detection | ||
|
||
User presence detection allows to check for connectivity or activity of users or devices. It has many | ||
applications from showing users' availability in a chat application to identify malfunctioning devices in an industrial process. | ||
|
||
This sample shows how to implement user presence detection effectively using Realm and Atlas resources. | ||
|
||
## Tracking local connectivity | ||
|
||
Clients could detect whether they are connected to Atlas via the `SyncSession.connectionState` | ||
property. The values of the connection state are `DISCONNECTED`, `CONNECTING`, or `CONNECTED`. | ||
|
||
Realm supports listening to updates to the connection state via the function `connectionStateAsFlow`, and simplifies listening to | ||
connectivity changes to: | ||
|
||
```kotlin | ||
realm.syncSession | ||
.connectionStateAsFlow() | ||
.collect {connectionStateChange -> | ||
// handle connection state | ||
} | ||
``` | ||
|
||
The local connectivity detection is used in this sample to display whether the current user is connected or not. | ||
|
||
## Tracking connectivity of external devices | ||
|
||
There are different approaches on how we can propagate to other parties the connectivity status of a | ||
client. | ||
|
||
### Forwarding logs | ||
|
||
This approach exclusively use App services resources to perform the detection exclusively on the server. | ||
|
||
App services would log any user connectivity change in the logs as a `Sync` type event. App services support forwarding these logs to predefined functions. | ||
|
||
![logs sample](logs.png "Logs") | ||
|
||
In this sample we have configured a forward log that forward all `Sync` events to a [function](functions/logPresenceDetector.js) that detects connectivity changes. This function analyzes each log to detect if a user has started/ended a session, then it upserts the changes in a [collection](data_sources/mongodb-atlas/presence-detection/user_status/schema.json) that tracks the connectivity for that user. | ||
|
||
This collection is part of a Sync Realm, so any changes to it would be automatically propagated all its subscriptions. | ||
|
||
![Flow](presence-flow.svg "Flow") | ||
|
||
The response time for this solution is up to a minute, that is what it takes to the log forwarding feature to post any new updates. Logs can be processed individually or in batches, while it does not affect the response time, doing it in batches debounces changes and eliminates redundant notification changes. | ||
|
||
### Alternatives | ||
|
||
Another solution that we have not covered in this sample is the clients actively notifying if they have connectivity. | ||
|
||
The clients would send a heart beat to the server each X seconds, then the server could poll for the clients that have not send a beat in Y amount of time, deeming them as disconnected. | ||
|
||
While this approach would improve the response time, it would use more resources and wouldn't scale as well. |
3 changes: 3 additions & 0 deletions
3
AppServicesUsageSamples/apps/presence-detection/auth/custom_user_data.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"enabled": false | ||
} |
12 changes: 12 additions & 0 deletions
12
AppServicesUsageSamples/apps/presence-detection/auth/providers.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"anon-user": { | ||
"name": "anon-user", | ||
"type": "anon-user", | ||
"disabled": false | ||
}, | ||
"api-key": { | ||
"name": "api-key", | ||
"type": "api-key", | ||
"disabled": true | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
AppServicesUsageSamples/apps/presence-detection/data_sources/mongodb-atlas/config.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"name": "mongodb-atlas", | ||
"type": "mongodb-atlas", | ||
"config": { | ||
"clusterName": "Cluster0", | ||
"readPreference": "primary", | ||
"wireProtocolEnabled": false | ||
}, | ||
"version": 1 | ||
} |
17 changes: 17 additions & 0 deletions
17
AppServicesUsageSamples/apps/presence-detection/data_sources/mongodb-atlas/default_rule.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"roles": [ | ||
{ | ||
"name": "readAll", | ||
"apply_when": {}, | ||
"document_filters": { | ||
"write": false, | ||
"read": true | ||
}, | ||
"read": true, | ||
"write": false, | ||
"insert": false, | ||
"delete": false, | ||
"search": true | ||
} | ||
] | ||
} |
1 change: 1 addition & 0 deletions
1
...ce-detection/data_sources/mongodb-atlas/presence-detection/user_status/relationships.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{} |
20 changes: 20 additions & 0 deletions
20
.../presence-detection/data_sources/mongodb-atlas/presence-detection/user_status/schema.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"properties": { | ||
"_id": { | ||
"bsonType": "objectId" | ||
}, | ||
"owner_id": { | ||
"bsonType": "string" | ||
}, | ||
"present": { | ||
"bsonType": "bool" | ||
} | ||
}, | ||
"required": [ | ||
"_id", | ||
"present", | ||
"owner_id" | ||
], | ||
"title": "user_status", | ||
"type": "object" | ||
} |
3 changes: 3 additions & 0 deletions
3
AppServicesUsageSamples/apps/presence-detection/environments/development.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"values": {} | ||
} |
3 changes: 3 additions & 0 deletions
3
AppServicesUsageSamples/apps/presence-detection/environments/no-environment.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"values": {} | ||
} |
3 changes: 3 additions & 0 deletions
3
AppServicesUsageSamples/apps/presence-detection/environments/production.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"values": {} | ||
} |
3 changes: 3 additions & 0 deletions
3
AppServicesUsageSamples/apps/presence-detection/environments/qa.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"values": {} | ||
} |
3 changes: 3 additions & 0 deletions
3
AppServicesUsageSamples/apps/presence-detection/environments/testing.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"values": {} | ||
} |
6 changes: 6 additions & 0 deletions
6
AppServicesUsageSamples/apps/presence-detection/functions/config.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[ | ||
{ | ||
"name": "logPresenceDetector", | ||
"private": false | ||
} | ||
] |
43 changes: 43 additions & 0 deletions
43
AppServicesUsageSamples/apps/presence-detection/functions/logPresenceDetector.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
exports = async function (logs) { | ||
// logs appear in ascending order | ||
for (let i = logs.length - 1; i >= 0; i--) { | ||
extract_presence(logs[i]) | ||
} | ||
}; | ||
|
||
async function extract_presence(log) { | ||
let type = log.type | ||
if (type !== "SYNC_SESSION_START" && type !== "SYNC_SESSION_END") return; | ||
|
||
let user_id = log.user_id; | ||
let present = type === "SYNC_SESSION_START"; | ||
|
||
console.log(`User ${user_id} present: ${present}`); | ||
|
||
update_presence(user_id, present); | ||
} | ||
|
||
async function update_presence(user_id, present) { | ||
const customUserDataCollection = context.services | ||
.get("mongodb-atlas") | ||
.db("presence-detection") | ||
.collection("user_status"); | ||
|
||
try { | ||
await customUserDataCollection.updateOne( | ||
{ | ||
owner_id: user_id, | ||
}, | ||
{ | ||
owner_id: user_id, | ||
present: present | ||
}, | ||
{ | ||
upsert: true | ||
} | ||
); | ||
} catch (e) { | ||
console.error(`Failed to create custom user data document for user: ${user_id}`); | ||
throw e | ||
} | ||
} |
3 changes: 3 additions & 0 deletions
3
AppServicesUsageSamples/apps/presence-detection/graphql/config.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"use_natural_pluralization": true | ||
} |
1 change: 1 addition & 0 deletions
1
AppServicesUsageSamples/apps/presence-detection/http_endpoints/config.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[] |
17 changes: 17 additions & 0 deletions
17
AppServicesUsageSamples/apps/presence-detection/log_forwarders/presenceDetector.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"name": "presenceDetector", | ||
"log_types": [ | ||
"sync" | ||
], | ||
"log_statuses": [ | ||
"success" | ||
], | ||
"policy": { | ||
"type": "batch" | ||
}, | ||
"action": { | ||
"type": "function", | ||
"name": "logPresenceDetector" | ||
}, | ||
"disabled": false | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
335 changes: 335 additions & 0 deletions
335
AppServicesUsageSamples/apps/presence-detection/presence-flow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions
8
AppServicesUsageSamples/apps/presence-detection/realm_config.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"app_id": "presence-detection", | ||
"config_version": 20210101, | ||
"name": "presence-detection", | ||
"location": "IE", | ||
"provider_region": "aws-eu-west-1", | ||
"deployment_model": "LOCAL" | ||
} |
16 changes: 16 additions & 0 deletions
16
AppServicesUsageSamples/apps/presence-detection/sync/config.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"type": "flexible", | ||
"state": "enabled", | ||
"development_mode_enabled": false, | ||
"service_name": "mongodb-atlas", | ||
"database_name": "presence-detection", | ||
"client_max_offline_days": 30, | ||
"is_recovery_mode_disabled": false, | ||
"permissions": { | ||
"rules": {}, | ||
"defaultRoles": [] | ||
}, | ||
"queryable_fields_names": [ | ||
"owner_id" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
...mples/demo/src/main/java/io/realm/appservicesusagesamples/presence/DependencyInjection.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright 2023 Realm Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express | ||
* or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.realm.appservicesusagesamples.presence | ||
|
||
import io.realm.appservicesusagesamples.Demos | ||
import io.realm.appservicesusagesamples.presence.ui.UserStatusListViewModel | ||
import org.koin.androidx.viewmodel.dsl.viewModel | ||
import org.koin.dsl.module | ||
|
||
val presenceDetectionModule = module { | ||
viewModel { | ||
UserStatusListViewModel( | ||
app = get(qualifier = Demos.USER_PRESENCE.qualifier), | ||
) | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
...demo/src/main/java/io/realm/appservicesusagesamples/presence/PresenceDetectionActivity.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* | ||
* Copyright 2023 Realm Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express | ||
* or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.realm.appservicesusagesamples.presence | ||
|
||
import android.os.Bundle | ||
import androidx.activity.ComponentActivity | ||
import androidx.activity.compose.setContent | ||
import androidx.compose.foundation.layout.fillMaxSize | ||
import androidx.compose.ui.Modifier | ||
import io.realm.appservicesusagesamples.presence.ui.UserStatusListScreen | ||
import io.realm.appservicesusagesamples.presence.ui.UserStatusListViewModel | ||
import io.realm.appservicesusagesamples.ui.theme.AppServicesUsageSamplesTheme | ||
import org.koin.android.scope.AndroidScopeComponent | ||
import org.koin.androidx.scope.activityRetainedScope | ||
import org.koin.androidx.viewmodel.ext.android.viewModel | ||
import org.koin.core.scope.Scope | ||
|
||
class PresenceDetectionActivity : ComponentActivity(), AndroidScopeComponent { | ||
override val scope: Scope by activityRetainedScope() | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
val viewModel: UserStatusListViewModel by viewModel() | ||
|
||
setContent { | ||
AppServicesUsageSamplesTheme { | ||
UserStatusListScreen( | ||
viewModel = viewModel, | ||
modifier = Modifier | ||
.fillMaxSize(), | ||
onLogout = { | ||
// close the app | ||
finish() | ||
} | ||
) | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.