Skip to content

Commit

Permalink
Apply suggestions from code review
Browse files Browse the repository at this point in the history
Co-authored-by: Andrew Meyer <[email protected]>
Co-authored-by: LJ <[email protected]>
  • Loading branch information
3 people authored Sep 13, 2023
1 parent 86545d7 commit dfc0684
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 28 deletions.
54 changes: 41 additions & 13 deletions examples/example-node-telemetry/README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,55 @@
# Telemetry demo app using data ingest and Atlas Charts
# Telemetry demo app using Data Ingest and Atlas Charts

A [node.js](https://nodejs.org) application to demonstrate how to use [Atlas Device Sync](https://www.mongodb.com/atlas/app-services/device-sync) and [Realm JavaScript](https://github.com/realm/realm-js) to read sensor data, store the data in [Atlas](https://www.mongodb.com/atlas), and visualize it with [Charts](https://www.mongodb.com/products/charts).
A [Node.js](https://nodejs.org) application to demonstrate how to use [Atlas Device Sync](https://www.mongodb.com/atlas/app-services/device-sync) and the [Realm Node.js SDK](https://www.mongodb.com/docs/realm/sdk/node/) to read sensor data, store the data in [Atlas](https://www.mongodb.com/atlas), and visualize it with [Atlas Charts](https://www.mongodb.com/products/charts). [Data Ingest](https://www.mongodb.com/docs/atlas/app-services/sync/configure/sync-settings/#data-ingest) is enabled since this app uses insert-only workloads.

The file structure is as follows:
## Project Structure

The following shows the project structure and the most relevant files.

```
├── README.md
├── package.json
├── src
│   ├── app.ts
│   ├── config.ts
│   └── models
│   ├── machine_info.ts
│   └── sensor_reading.ts
│ ├── models
│ │ ├── machine_info.ts
│ │ └── sensor_reading.ts
│ ├── app.ts
│ └── config.ts
├── package.json
└── README.md
```

* `src/app.ts` - the actual application
* `src/config.ts` - contains the configuration (app id)
* `src/config.ts` - contains the configuration (Atlas App ID)
* `src/models/` - the model classes

## Altas App Services
## Use Cases

This app focuses on showing how to use Data Ingest for heavy client-side insert-only workloads. It specifically addresses the following points:

* Using the Data Ingest sync strategy via asymmetric Realm objects.
* Reading sensor data (system load averages, uptime, and free memory).
* Inserting sensor data every few seconds and syncing it to Atlas.
* (The data in Atlas can be visualized via Atlas Charts, but since this is a Node.js app, the visualization is not shown.)

### Realm Details

* RealmJS version: ^12.1.0
* Device Sync type: [Flexible](https://www.mongodb.com/docs/realm/sdk/node/sync/flexible-sync/) with [Data Ingest](https://www.mongodb.com/docs/atlas/app-services/sync/configure/sync-settings/#data-ingest)

## Getting Started

### Prerequisites

* [Node.js](https://nodejs.org/)

### Set Up an Atlas App Services App

To sync Realm data you must first:

1. [Create an App Services App](https://www.mongodb.com/docs/atlas/app-services/manage-apps/create/create-with-ui/)
2. [Enable Anonymous Authentication](https://www.mongodb.com/docs/atlas/app-services/authentication/anonymous/)
3. [Enable Flexible Sync](https://www.mongodb.com/docs/atlas/app-services/sync/configure/enable-sync/) with **Development Mode** on.

To use the app together with Atlas App Services, you need to create an Atlas database and collection. Moreover, you need to create App service and enable Device Sync.
After running the client and seeing the available collection in Atlas, [set write permissions](https://www.mongodb.com/docs/atlas/app-services/rules/roles/#define-roles---permissions) for the collection.

The schema to use (App Services / Data Access / Schema):

Expand Down
4 changes: 3 additions & 1 deletion examples/example-node-telemetry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
"private": true,
"version": "0.1.0",
"description": "A demonstration of how to use data ingest to store and visualize sensor data",
"main": "index.js",
"main": "src/app.ts",
"scripts": {
"build": "tsc -p tsconfig.build.json",
"lint": "eslint --ext .js,.mjs,.ts .",
"start": "npm run build && node dist/app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
Expand All @@ -22,6 +23,7 @@
"realm": "^12.1.0"
},
"devDependencies": {
"@types/debug": "^4.1.8",
"@types/node": "^20.5.7",
"eslint": "^8.48.0",
"typescript": "^4.9.5"
Expand Down
22 changes: 13 additions & 9 deletions examples/example-node-telemetry/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
//
////////////////////////////////////////////////////////////////////////////

import * as os from "os";
import os from "node:os";
import { machineId } from "node-machine-id";

import createDebug from "debug";
Expand Down Expand Up @@ -53,15 +53,19 @@ async function readMachineInfo() {
}

async function main() {
// Initialize the app using the app id. You need to copy it from https://realm.mongodb.com
// Initialize the app using the App ID. To copy it, see:
// https://www.mongodb.com/docs/atlas/app-services/apps/metadata/#std-label-find-your-app-id
const app = new Realm.App(config.appId);
debug(`App ${config.appId} has been initiated`);
// We are using an anonymous user, and you can switch to any auth provider if needed

// We are using an anonymous user for this example app, but you can modify this to
// use any of the available auth providers.
debug(`Logging in`);
const user = await app.logIn(Realm.Credentials.anonymous());
debug(`User ${user.id} has been logged in`);
// For data ingest (`asymmetric: true` in `SensorReading`) you don't need any
// subscriptions for flexible sync

// For Data Ingest (`asymmetric: true` in the `SensorReading` schema) you don't need
// to set up any subscriptions for flexible sync since no data will be synced to the device.
debug("Opening Realm");
const realm = await Realm.open({
schema: [SensorReading, MachineInfo],
Expand All @@ -71,18 +75,18 @@ async function main() {
},
});

// The metadata about the computer will not change
// The metadata about the computer will not change, thus we only read it once.
const machineInfo = await readMachineInfo();
const intervalId = setInterval(() => {
const now = new Date();
const measurement = readSensorData();
const obj = {
const obj: SensorReading = {
timestamp: now,
machineInfo,
...measurement,
};
debug("Writing new sensor reading");
realm.write(() => realm.create(SensorReading.name, obj));
realm.write(() => realm.create(SensorReading, obj));
}, tenSeconds);

// Catch CTRL-C in a nice way
Expand All @@ -93,7 +97,7 @@ async function main() {
clearInterval(intervalId);
debug("Sync any outstanding changes");
await realm.syncSession?.uploadAllLocalChanges();
debug("Cloing Realm");
debug("Closing Realm");
realm.close();
debug(`Logging out user ${user.id}`);
await user.logOut();
Expand Down
8 changes: 4 additions & 4 deletions examples/example-node-telemetry/src/models/sensor_reading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ export class SensorReading extends Realm.Object {
timestamp!: Date;
uptime!: number;
freemem!: number;
loadAvg!: [number];
loadAvg!: Realm.List<number>;
machineInfo!: MachineInfo;

static schema: ObjectSchema = {
name: "SensorReading",
asymmetric: true,
primaryKey: "_id",
properties: {
_id: { type: "objectId", default: () => new BSON.ObjectID() },
timestamp: { type: "date", optional: false, default: () => new Date() },
_id: { type: "objectId", default: () => new BSON.ObjectId() },
timestamp: "date",
uptime: "float",
freemem: "int",
loadAvg: { type: "list", objectType: "float" },
loadAvg: "float[]",
machineInfo: "MachineInfo",
},
};
Expand Down
1 change: 0 additions & 1 deletion examples/example-node-telemetry/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"target": "es2018",
"moduleResolution": "node",
Expand Down

0 comments on commit dfc0684

Please sign in to comment.