Skip to content

Commit ba298bc

Browse files
authored
Add ruby equivalent of node.js app (#487)
1 parent bbe7af9 commit ba298bc

File tree

11 files changed

+570
-0
lines changed

11 files changed

+570
-0
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Logs
2+
logs
3+
*.log
4+
5+
# Runtime data
6+
pids
7+
*.pid
8+
*.seed
9+
10+
# Directory for instrumented libs generated by jscoverage/JSCover
11+
lib-cov
12+
13+
# Coverage directory used by tools like istanbul
14+
coverage
15+
16+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17+
.grunt
18+
19+
# node-waf configuration
20+
.lock-wscript
21+
22+
# Compiled binary addons (http://nodejs.org/api/addons.html)
23+
build/Release
24+
25+
# Dependency directory
26+
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
27+
node_modules
28+
29+
server/*.spec.js
30+
kubernetes
31+
32+
# Don't copy default config
33+
config.yaml
34+
35+
# Ruby specific
36+
*.gem
37+
*.rbc
38+
.bundle
39+
.config
40+
coverage
41+
InstalledFiles
42+
lib/bundler/man
43+
pkg
44+
rdoc
45+
spec/reports
46+
test/tmp
47+
test/version_tmp
48+
tmp
49+
.bundle/
50+
vendor/bundle
51+
Gemfile.lock
52+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM ruby:3.3-bookworm AS build
2+
3+
COPY . /app
4+
5+
WORKDIR /app
6+
7+
RUN bundle install
8+
9+
FROM ruby:3.3-slim-bookworm
10+
11+
COPY --from=build /app /app
12+
COPY --from=build /usr/local/bundle /usr/local/bundle
13+
14+
WORKDIR /app
15+
16+
CMD ["ruby", "app.rb"]
17+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# frozen_string_literal: true
2+
3+
source 'https://rubygems.org'
4+
5+
gem 'pg'
6+
gem 'prometheus-client'
7+
gem 'rack'
8+
gem 'yaml'
9+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
GEM
2+
remote: https://rubygems.org/
3+
specs:
4+
base64 (0.3.0)
5+
pg (1.6.2)
6+
pg (1.6.2-aarch64-linux)
7+
pg (1.6.2-aarch64-linux-musl)
8+
pg (1.6.2-arm64-darwin)
9+
pg (1.6.2-x86_64-darwin)
10+
pg (1.6.2-x86_64-linux)
11+
pg (1.6.2-x86_64-linux-musl)
12+
prometheus-client (4.2.5)
13+
base64
14+
rack (3.2.4)
15+
yaml (0.4.0)
16+
17+
PLATFORMS
18+
aarch64-linux
19+
aarch64-linux-musl
20+
arm64-darwin
21+
ruby
22+
x86_64-darwin
23+
x86_64-linux
24+
x86_64-linux-musl
25+
26+
DEPENDENCIES
27+
pg
28+
prometheus-client
29+
rack
30+
yaml
31+
32+
BUNDLED WITH
33+
2.7.2
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
# Ruby Device Management API
2+
3+
A Ruby-based HTTP server application for managing IoT devices with PostgreSQL database integration and Prometheus metrics. This is a Ruby equivalent of the Node.js application in the `node-app` folder.
4+
5+
## Overview
6+
7+
This application provides a RESTful API for managing device records, including:
8+
- Device listing and creation
9+
- PostgreSQL database integration
10+
- Prometheus metrics for monitoring
11+
- Health check endpoint
12+
13+
## Features
14+
15+
- **HTTP Server**: Built with Rack and WEBrick
16+
- **Database**: PostgreSQL integration using the `pg` gem
17+
- **Metrics**: Prometheus histogram metrics for tracking database operation duration
18+
- **RESTful API**: Endpoints for device management
19+
- **Docker Support**: Multi-stage Dockerfile for containerized deployment
20+
21+
## Prerequisites
22+
23+
- Ruby 3.3 or higher
24+
- PostgreSQL database
25+
- Bundler gem (usually comes with Ruby)
26+
27+
## Installation
28+
29+
1. Install dependencies:
30+
```bash
31+
bundle install
32+
```
33+
34+
## Configuration
35+
36+
The application uses a `config.yaml` file for configuration. Create or modify `config.yaml`:
37+
38+
```yaml
39+
---
40+
appPort: 8080
41+
db:
42+
user: node
43+
password: devops123
44+
host: postgresql.antonputra.pvt
45+
database: mydb
46+
maxConnections: 75
47+
```
48+
49+
**Note**: Update the database connection details to match your PostgreSQL setup.
50+
51+
## Running the Application
52+
53+
### Local Development
54+
55+
1. Ensure PostgreSQL is running and accessible
56+
2. Make sure the database and `node_device` table exist (see migration notes below)
57+
3. Start the server:
58+
```bash
59+
ruby app.rb
60+
```
61+
62+
The server will start on `http://0.0.0.0:8080` (or the port specified in `config.yaml`).
63+
64+
### Using Docker
65+
66+
1. Build the Docker image:
67+
```bash
68+
docker build -t ruby-app-node-equivalent .
69+
```
70+
71+
2. Run the container:
72+
```bash
73+
docker run -p 8080:8080 ruby-app-node-equivalent
74+
```
75+
76+
## API Endpoints
77+
78+
### GET /api/devices
79+
80+
Returns a list of sample devices.
81+
82+
**Response:**
83+
```json
84+
[
85+
{
86+
"id": 1,
87+
"uuid": "9add349c-c35c-4d32-ab0f-53da1ba40a2a",
88+
"mac": "5F-33-CC-1F-43-82",
89+
"firmware": "2.1.6",
90+
"created_at": "2024-05-28T15:21:51.137Z",
91+
"updated_at": "2024-05-28T15:21:51.137Z"
92+
},
93+
...
94+
]
95+
```
96+
97+
### POST /api/devices
98+
99+
Creates a new device in the database.
100+
101+
**Request Body:**
102+
```json
103+
{
104+
"mac": "AA-BB-CC-DD-EE-FF",
105+
"firmware": "1.0.0"
106+
}
107+
```
108+
109+
**Response (201 Created):**
110+
```json
111+
{
112+
"id": 4,
113+
"uuid": "generated-uuid",
114+
"mac": "AA-BB-CC-DD-EE-FF",
115+
"firmware": "1.0.0",
116+
"created_at": "2024-11-08T12:34:56.789Z",
117+
"updated_at": "2024-11-08T12:34:56.789Z"
118+
}
119+
```
120+
121+
**Error Response (400 Bad Request):**
122+
```json
123+
{
124+
"message": "Error message"
125+
}
126+
```
127+
128+
### GET /metrics
129+
130+
Returns Prometheus metrics in text format. This endpoint exposes the `myapp_request_duration_seconds` histogram metric that tracks database operation durations.
131+
132+
### GET /healthz
133+
134+
Health check endpoint. Returns `OK` if the server is running.
135+
136+
**Response:**
137+
```
138+
OK
139+
```
140+
141+
## Database Schema
142+
143+
The application expects a PostgreSQL table named `node_device` with the following structure:
144+
145+
```sql
146+
CREATE TABLE node_device (
147+
id SERIAL PRIMARY KEY,
148+
uuid VARCHAR(255) NOT NULL,
149+
mac VARCHAR(255) NOT NULL,
150+
firmware VARCHAR(255) NOT NULL,
151+
created_at TIMESTAMP NOT NULL,
152+
updated_at TIMESTAMP NOT NULL
153+
);
154+
```
155+
156+
## Project Structure
157+
158+
```
159+
ruby-app-node-equivalent/
160+
├── app.rb # Main HTTP server application
161+
├── config.rb # Configuration loader
162+
├── config.yaml # Configuration file
163+
├── db.rb # PostgreSQL database connection
164+
├── devices.rb # Device database operations
165+
├── metrics.rb # Prometheus metrics setup
166+
├── Gemfile # Ruby dependencies
167+
├── Dockerfile # Docker build configuration
168+
├── .dockerignore # Docker ignore patterns
169+
└── README.md # This file
170+
```
171+
172+
## Dependencies
173+
174+
- **pg**: PostgreSQL database adapter
175+
- **prometheus-client**: Prometheus metrics client library
176+
- **rack**: Web server interface
177+
- **yaml**: YAML configuration parsing (built-in)
178+
179+
## Metrics
180+
181+
The application tracks database operation duration using a Prometheus histogram metric:
182+
183+
- **Metric Name**: `myapp_request_duration_seconds`
184+
- **Type**: Histogram
185+
- **Labels**: `op` (operation type, e.g., "db")
186+
- **Buckets**: Custom buckets optimized for low-latency operations (0.00001 to 17.5 seconds)
187+
188+
## Error Handling
189+
190+
- Database errors are caught and returned as 400 Bad Request with an error message
191+
- Invalid JSON in POST requests will result in a 400 error
192+
- All errors are logged to stdout
193+
194+
## Notes
195+
196+
- The server uses a 60-second keep-alive timeout
197+
- UUIDs are automatically generated using Ruby's `SecureRandom.uuid`
198+
- Timestamps are generated in ISO 8601 format with millisecond precision
199+
- The application uses a single PostgreSQL connection (connection pooling can be added if needed)
200+

0 commit comments

Comments
 (0)