Skip to content

Commit 7649d53

Browse files
authored
Merge pull request #10 from steveiliop56/refactor/rewrite
refactor: rewrite app with chi and sqlc
2 parents c11e460 + 984377c commit 7649d53

34 files changed

Lines changed: 691 additions & 934 deletions

.gitignore

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
# data
2-
data/analytics.db
2+
data
33

44
# debug
55
__debug_*
66

7-
# bench
7+
# build out
8+
tinyauth-analytics
9+
10+
# benchmarks
811
bench

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"mode": "auto",
99
"program": "${fileDirname}",
1010
"env": {
11-
"DB_PATH": "./data/analytics.db",
11+
"DATABASE_PATH": "./data/analytics.db",
1212
"PORT": "8080",
1313
"ADDRESS": "0.0.0.0",
1414
"TRUSTED_PROXIES": "0.0.0.0",

Dockerfile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@ COPY go.sum ./
1010

1111
RUN go mod download
1212

13+
COPY ./cache.go ./
14+
COPY ./health_handler.go ./
15+
COPY ./instances_handler.go ./
1316
COPY ./main.go ./
14-
COPY ./internal ./internal
17+
COPY ./rate_limiter.go ./
18+
COPY ./database ./database
1519

1620
RUN CGO_ENABLED=0 go build -ldflags "-s -w -X main.version=${VERSION}"
1721

README.md

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ A simple server to transparently collect version information from Tinyauth insta
44

55
## How does it work
66

7-
Every Tinyauth instance runs a goroutine (unless you choose to opt-out) that does a "heartbeat" every 12 hours indicating the instance is still alive. The heartbeat contains the UUID generated by Tinyauth on start up and the version information. The server stores them in the SQLite database alongside with the last seen date. When you request all the instances, the server responds with an array containing the versions, UUIDs and last seen dates. In order to increase transparency, if the `LOG_LEVEL` is configured to `debug` or `trace`, the server will return a warning both in the instances and heartbeat endpoint in order to inform the user that sensitive information like IP addresses may be logged.
7+
Every Tinyauth instance runs a goroutine (unless you choose to opt-out) that does a "heartbeat" every 12 hours indicating the instance is still alive. The heartbeat contains the UUID generated by Tinyauth on start up and the version information. The server stores them in the SQLite database alongside with the last seen date. When you request all the instances, the server responds with an array containing the versions, UUIDs and last seen dates.
88

99
## Running
1010

@@ -18,15 +18,14 @@ docker compose up -d
1818

1919
The server is configured using environment variables, the following options are supported:
2020

21-
| Name | Type | Description | Default |
22-
| ---------------------- | ------------ | ---------------------------------------------------------- | -------------------- |
23-
| `DB_PATH` | string | Path to the SQLite database file. | `/data/analytics.db` |
24-
| `PORT` | number | The port to run the server on. | `8080` |
25-
| `ADDRESS` | string | The address to bind the server to. | `0.0.0.0` |
26-
| `RATE_LIMIT_COUNT` | number | Maximum number of requests per minute per IP. | `3` |
27-
| `CORS_ALLOWED_ORIGINS` | string/array | Comma-separated list of allowed CORS origins. | `*` |
28-
| `TRUSTED_PROXIES` | string/array | Comma-separated list of trusted proxy IPs. | `""` (empty) |
29-
| `LOG_LEVEL` | string | Log level (trace, debug, info, warn, error, fatal, panic). | `info` |
21+
| Name | Type | Description | Default |
22+
| ---------------------- | ------------ | --------------------------------------------- | -------------------- |
23+
| `DATABASE_PATH` | string | Path to the SQLite database file. | `/data/analytics.db` |
24+
| `PORT` | number | The port to run the server on. | `8080` |
25+
| `ADDRESS` | string | The address to bind the server to. | `0.0.0.0` |
26+
| `RATE_LIMIT_COUNT` | number | Maximum number of requests per minute per IP. | `3` |
27+
| `CORS_ALLOWED_ORIGINS` | string/array | Comma-separated list of allowed CORS origins. | `*` |
28+
| `TRUSTED_PROXIES` | string/array | Comma-separated list of trusted proxy IPs. | `` |
3029

3130
## Contributing
3231

cache.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package main
2+
3+
import (
4+
"sync"
5+
"time"
6+
)
7+
8+
type cacheField struct {
9+
value any
10+
expire int64
11+
}
12+
13+
type Cache struct {
14+
cache map[string]cacheField
15+
mutex sync.RWMutex
16+
}
17+
18+
func NewCache() *Cache {
19+
cache := &Cache{
20+
cache: make(map[string]cacheField),
21+
}
22+
cache.cleanup()
23+
return cache
24+
}
25+
26+
func (c *Cache) Set(key string, value any, ttl int64) {
27+
c.mutex.Lock()
28+
defer c.mutex.Unlock()
29+
30+
expire := time.Now().Add(time.Duration(ttl) * time.Second).Unix()
31+
32+
c.cache[key] = cacheField{
33+
value: value,
34+
expire: expire,
35+
}
36+
}
37+
38+
func (c *Cache) Get(key string) (any, bool) {
39+
c.mutex.RLock()
40+
41+
field, ok := c.cache[key]
42+
43+
if !ok {
44+
c.mutex.RUnlock()
45+
return nil, false
46+
}
47+
48+
if time.Now().Unix() > field.expire {
49+
c.mutex.RUnlock()
50+
c.Delete(key)
51+
return nil, false
52+
}
53+
54+
c.mutex.RUnlock()
55+
return field.value, true
56+
}
57+
58+
func (c *Cache) Delete(key string) {
59+
c.mutex.Lock()
60+
defer c.mutex.Unlock()
61+
delete(c.cache, key)
62+
}
63+
64+
func (c *Cache) Flush() {
65+
c.mutex.Lock()
66+
defer c.mutex.Unlock()
67+
c.cache = make(map[string]cacheField, 0)
68+
}
69+
70+
func (c *Cache) cleanup() {
71+
go func() {
72+
ticker := time.NewTicker(24 * time.Hour)
73+
defer ticker.Stop()
74+
75+
for range ticker.C {
76+
c.mutex.Lock()
77+
for key, field := range c.cache {
78+
if time.Now().Unix() > field.expire {
79+
delete(c.cache, key)
80+
}
81+
}
82+
c.mutex.Unlock()
83+
}
84+
}()
85+
}

data/.gitkeep

Whitespace-only changes.

database/queries/db.go

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

database/queries/models.go

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

database/queries/query.sql.go

Lines changed: 123 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docker-compose.dev.yml

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,26 @@ services:
1212
- RATE_LIMIT_COUNT=15
1313
- CORS_ALLOWED_ORIGINS=*
1414
- TRUSTED_PROXIES=0.0.0.0
15-
- LOG_LEVEL=debug
1615
volumes:
1716
- ./data:/data
1817
ports:
1918
- 8080:8080
2019
restart: unless-stopped
2120

22-
analytics-dashboard:
23-
build:
24-
context: ./dashboard
25-
dockerfile: Dockerfile
26-
args:
27-
- VERSION=development
28-
environment:
29-
- PORT=8090
30-
- ADDRESS=0.0.0.0
31-
- API_SERVER=http://tinyauth-analytics:8080
32-
- PAGE_SIZE=10
33-
- REFRESH_INTERVAL=1
34-
ports:
35-
- 8090:8090
36-
restart: unless-stopped
37-
depends_on:
38-
- tinyauth-analytics
21+
# analytics-dashboard:
22+
# build:
23+
# context: ./dashboard
24+
# dockerfile: Dockerfile
25+
# args:
26+
# - VERSION=development
27+
# environment:
28+
# - PORT=8090
29+
# - ADDRESS=0.0.0.0
30+
# - API_SERVER=http://tinyauth-analytics:8080
31+
# - PAGE_SIZE=10
32+
# - REFRESH_INTERVAL=1
33+
# ports:
34+
# - 8090:8090
35+
# restart: unless-stopped
36+
# depends_on:
37+
# - tinyauth-analytics

0 commit comments

Comments
 (0)