# brillery/mediahub architecture

> Architecture diagram of the GitHub repository brillery/mediahub, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-28). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/brillery/mediahub
- Repository: https://github.com/brillery/mediahub
- Video tour (about a minute): https://gitdiagram.com/brillery/mediahub/video

## Overview

This repository is a media upload and short-link system: users browse a Vue interface and upload files through Mediahub, which stores media and requests short links from a separate gRPC service. Short-link resolution is also exposed through an HTTP proxy; a scheduled job flushes Redis access counts to MySQL. The short-link server excerpt supports the cache, lock, persistence, and warmup relationships shown below. Several controller, proxy, data, and cron implementations were not sampled, so their internal call wiring is intentionally limited.

Main entry points: [`shorturl/shorturl-server/server/server.go`](https://github.com/brillery/mediahub/blob/master/shorturl/shorturl-server/server/server.go) (Short-link service), [`shorturl/pkg/db/redis/redis.go`](https://github.com/brillery/mediahub/blob/master/shorturl/pkg/db/redis/redis.go) (Redis cache and counts), [`mediahub/routers/routers.go`](https://github.com/brillery/mediahub/blob/master/mediahub/routers/routers.go) (API routes), [`mediahub/controller/file.go`](https://github.com/brillery/mediahub/blob/master/mediahub/controller/file.go) (File controller)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_web["Web client"]
  node_webapp["Vue app<br/>[main.ts]"]
  node_home["Home view<br/>[home.vue]"]
  node_uploadui["Upload UI<br/>[upload.vue]"]
  node_webapi["Web API client<br/>[api.ts]"]
end

subgraph group_media["MediaHub API"]
  node_mediaapi["MediaHub HTTP API<br/>[main.go]"]
  node_routes["API routes<br/>[routers.go]"]
  node_filectrl["File controller<br/>[file.go]"]
  node_homectrl["Home controller<br/>[home.go]"]
  node_shortclient["Short-link client<br/>[client.go]"]
  node_grpcpool["gRPC connection pool<br/>[client_pool.go]"]
end

subgraph group_short["Short-link services"]
  node_shortgrpc["Short-link gRPC server<br/>[main.go]"]
  node_shortsvc["Short-link service<br/>[server.go]"]
  node_urlmap["URL mapping data<br/>[url_map.go]"]
  node_cache["Two-level cache<br/>[cache.go]"]
  node_lock["Distributed locks<br/>[lock.go]"]
  node_counter["Access counter<br/>[access_counter.go]"]
  node_proxy["Redirect proxy<br/>[proxy.go]"]
  node_proxyclient["Proxy gRPC client<br/>[client.go]"]
  node_cron["Count flush job<br/>[access_count.go]"]
  node_crondb["Cron MySQL access<br/>[mysql.go]"]
end

subgraph group_state["Persistence and storage"]
  node_cos[("COS media storage<br/>[cos.go]")]
  node_mysql[("MySQL mappings<br/>[mysql.go]")]
  node_redis[("Redis cache and counts<br/>[redis.go]")]
end

node_visitor(("Visitor"))
node_cosservice[("COS service")]

node_visitor -->|"uses"| node_webapp
node_webapp -->|"renders"| node_home
node_home -->|"offers upload"| node_uploadui
node_uploadui -->|"requests API"| node_webapi
node_visitor -->|"uploads file"| node_mediaapi
node_mediaapi -->|"dispatches"| node_routes
node_routes -->|"routes upload"| node_filectrl
node_routes -->|"routes home"| node_homectrl
node_filectrl -->|"stores media"| node_cos
node_cos -->|"stores objects"| node_cosservice
node_filectrl -->|"requests short link"| node_shortclient
node_shortclient -->|"gets connection"| node_grpcpool
node_shortgrpc -->|"registers service"| node_shortsvc
node_shortsvc -->|"reads/writes mappings"| node_urlmap
node_shortsvc -->|"reads/fills cache"| node_cache
node_shortsvc -->|"coordinates misses"| node_lock
node_shortsvc -->|"increments visits"| node_counter
node_urlmap -->|"persists mappings"| node_mysql
node_cache -->|"reads/writes cache"| node_redis
node_lock -->|"coordinates access"| node_redis
node_counter -->|"increments counts"| node_redis
node_visitor -->|"opens short link"| node_proxy
node_proxy -->|"resolves link"| node_proxyclient
node_proxyclient -->|"calls gRPC"| node_shortgrpc
node_cron -->|"reads counts"| node_redis
node_cron -->|"flushes counts"| node_crondb
node_crondb -->|"updates totals"| node_mysql

click node_webapp "https://github.com/brillery/mediahub/blob/master/mediahub-web/src/main.ts"
click node_home "https://github.com/brillery/mediahub/blob/master/mediahub-web/src/views/home.vue"
click node_uploadui "https://github.com/brillery/mediahub/blob/master/mediahub-web/src/views/components/upload.vue"
click node_webapi "https://github.com/brillery/mediahub/blob/master/mediahub-web/src/api/api.ts"
click node_mediaapi "https://github.com/brillery/mediahub/blob/master/mediahub/main.go"
click node_routes "https://github.com/brillery/mediahub/blob/master/mediahub/routers/routers.go"
click node_filectrl "https://github.com/brillery/mediahub/blob/master/mediahub/controller/file.go"
click node_homectrl "https://github.com/brillery/mediahub/blob/master/mediahub/controller/home.go"
click node_cos "https://github.com/brillery/mediahub/blob/master/mediahub/pkg/storage/cos/cos.go"
click node_shortclient "https://github.com/brillery/mediahub/blob/master/mediahub/services/shorturl/client.go"
click node_grpcpool "https://github.com/brillery/mediahub/blob/master/mediahub/pkg/grpc_client_pool/client_pool.go"
click node_shortgrpc "https://github.com/brillery/mediahub/blob/master/shorturl/shorturl-server/main.go"
click node_shortsvc "https://github.com/brillery/mediahub/blob/master/shorturl/shorturl-server/server/server.go"
click node_urlmap "https://github.com/brillery/mediahub/blob/master/shorturl/shorturl-server/data/url_map.go"
click node_cache "https://github.com/brillery/mediahub/blob/master/shorturl/shorturl-server/cache/cache.go"
click node_lock "https://github.com/brillery/mediahub/blob/master/shorturl/shorturl-server/cache/lock.go"
click node_counter "https://github.com/brillery/mediahub/blob/master/shorturl/shorturl-server/cache/access_counter.go"
click node_mysql "https://github.com/brillery/mediahub/blob/master/shorturl/pkg/db/mysql/mysql.go"
click node_redis "https://github.com/brillery/mediahub/blob/master/shorturl/pkg/db/redis/redis.go"
click node_proxy "https://github.com/brillery/mediahub/blob/master/shorturl-proxy/proxy/proxy.go"
click node_proxyclient "https://github.com/brillery/mediahub/blob/master/shorturl-proxy/services/shorturl/client.go"
click node_cron "https://github.com/brillery/mediahub/blob/master/shorturl-crontab/cron/access_count.go"
click node_crondb "https://github.com/brillery/mediahub/blob/master/shorturl-crontab/pkg/db/mysql/mysql.go"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_webapp,node_home,node_uploadui,node_webapi toneBlue
class node_mediaapi,node_routes,node_filectrl,node_homectrl,node_shortclient,node_grpcpool,node_cosservice toneAmber
class node_shortgrpc,node_shortsvc,node_urlmap,node_cache,node_lock,node_counter,node_proxy,node_proxyclient,node_cron,node_crondb toneMint
class node_cos,node_mysql,node_redis toneRose
class node_visitor toneIndigo
```

## Components

### Web client

- [Vue app](https://github.com/brillery/mediahub/blob/master/mediahub-web/src/main.ts): `mediahub-web/src/main.ts`
- [Home view](https://github.com/brillery/mediahub/blob/master/mediahub-web/src/views/home.vue): `mediahub-web/src/views/home.vue`
- [Upload UI](https://github.com/brillery/mediahub/blob/master/mediahub-web/src/views/components/upload.vue): `mediahub-web/src/views/components/upload.vue`
- [Web API client](https://github.com/brillery/mediahub/blob/master/mediahub-web/src/api/api.ts): `mediahub-web/src/api/api.ts`

### MediaHub API

- [MediaHub HTTP API](https://github.com/brillery/mediahub/blob/master/mediahub/main.go): `mediahub/main.go`
- [API routes](https://github.com/brillery/mediahub/blob/master/mediahub/routers/routers.go): `mediahub/routers/routers.go`
- [File controller](https://github.com/brillery/mediahub/blob/master/mediahub/controller/file.go): `mediahub/controller/file.go`
- [Home controller](https://github.com/brillery/mediahub/blob/master/mediahub/controller/home.go): `mediahub/controller/home.go`
- [Short-link client](https://github.com/brillery/mediahub/blob/master/mediahub/services/shorturl/client.go): `mediahub/services/shorturl/client.go`
- [gRPC connection pool](https://github.com/brillery/mediahub/blob/master/mediahub/pkg/grpc_client_pool/client_pool.go): `mediahub/pkg/grpc_client_pool/client_pool.go`

### Short-link services

- [Short-link gRPC server](https://github.com/brillery/mediahub/blob/master/shorturl/shorturl-server/main.go): `shorturl/shorturl-server/main.go`
- [Short-link service](https://github.com/brillery/mediahub/blob/master/shorturl/shorturl-server/server/server.go): `shorturl/shorturl-server/server/server.go`
- [URL mapping data](https://github.com/brillery/mediahub/blob/master/shorturl/shorturl-server/data/url_map.go): `shorturl/shorturl-server/data/url_map.go`
- [Two-level cache](https://github.com/brillery/mediahub/blob/master/shorturl/shorturl-server/cache/cache.go): `shorturl/shorturl-server/cache/cache.go`
- [Distributed locks](https://github.com/brillery/mediahub/blob/master/shorturl/shorturl-server/cache/lock.go): `shorturl/shorturl-server/cache/lock.go`
- [Access counter](https://github.com/brillery/mediahub/blob/master/shorturl/shorturl-server/cache/access_counter.go): `shorturl/shorturl-server/cache/access_counter.go`
- [Redirect proxy](https://github.com/brillery/mediahub/blob/master/shorturl-proxy/proxy/proxy.go): `shorturl-proxy/proxy/proxy.go`
- [Proxy gRPC client](https://github.com/brillery/mediahub/blob/master/shorturl-proxy/services/shorturl/client.go): `shorturl-proxy/services/shorturl/client.go`
- [Count flush job](https://github.com/brillery/mediahub/blob/master/shorturl-crontab/cron/access_count.go): `shorturl-crontab/cron/access_count.go`
- [Cron MySQL access](https://github.com/brillery/mediahub/blob/master/shorturl-crontab/pkg/db/mysql/mysql.go): `shorturl-crontab/pkg/db/mysql/mysql.go`

### Persistence and storage

- [COS media storage](https://github.com/brillery/mediahub/blob/master/mediahub/pkg/storage/cos/cos.go): `mediahub/pkg/storage/cos/cos.go`
- [MySQL mappings](https://github.com/brillery/mediahub/blob/master/shorturl/pkg/db/mysql/mysql.go): `shorturl/pkg/db/mysql/mysql.go`
- [Redis cache and counts](https://github.com/brillery/mediahub/blob/master/shorturl/pkg/db/redis/redis.go): `shorturl/pkg/db/redis/redis.go`

### Other components

- **Visitor**
- **COS service**

## Connections

- Visitor → Vue app: uses
- Vue app → Home view: renders
- Home view → Upload UI: offers upload
- Upload UI → Web API client: requests API
- Visitor → MediaHub HTTP API: uploads file
- MediaHub HTTP API → API routes: dispatches
- API routes → File controller: routes upload
- API routes → Home controller: routes home
- File controller → COS media storage: stores media
- COS media storage → COS service: stores objects
- File controller → Short-link client: requests short link
- Short-link client → gRPC connection pool: gets connection
- Short-link gRPC server → Short-link service: registers service
- Short-link service → URL mapping data: reads/writes mappings
- Short-link service → Two-level cache: reads/fills cache
- Short-link service → Distributed locks: coordinates misses
- Short-link service → Access counter: increments visits
- URL mapping data → MySQL mappings: persists mappings
- Two-level cache → Redis cache and counts: reads/writes cache
- Distributed locks → Redis cache and counts: coordinates access
- Access counter → Redis cache and counts: increments counts
- Visitor → Redirect proxy: opens short link
- Redirect proxy → Proxy gRPC client: resolves link
- Proxy gRPC client → Short-link gRPC server: calls gRPC
- Count flush job → Redis cache and counts: reads counts
- Count flush job → Cron MySQL access: flushes counts
- Cron MySQL access → MySQL mappings: updates totals
