Skip to content

Black-persik/URL_shortener

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

URL Shortener + Click Analytics (Go)

Сервис сокращения ссылок на Go с асинхронным сбором кликов и базовой статистикой.

Цель проекта: показать backend-навыки (REST API, PostgreSQL, Docker, конкурентность в Go через worker pool + channels, корректное завершение через context).


Возможности

  • Создание коротких ссылок через REST API
  • Редирект по короткому коду
  • Сбор кликов асинхронно (очередь на channel + worker pool)
  • Статистика по ссылке: total_clicks
  • Хранение данных в PostgreSQL
  • Миграции БД через goose
  • Конфигурация через переменные окружения
  • Graceful shutdown (остановка воркеров через context, дожим батча)

Стек

  • Go
  • HTTP: стандартный net/http
  • PostgreSQL
  • Docker + Docker Compose
  • Миграции: goose
  • Makefile для удобного управления проектом

Архитектура

Почему клики пишутся асинхронно?
Чтобы редирект был быстрым и не зависел от записи в БД на “горячем пути”.

Поток данных:

Client -> API
POST /links             -> сохраняет ссылку в Postgres
GET  /{code}            -> читает original_url -> редиректит
-> отправляет click event в channel

Click workers (N goroutines) читают события из channel
-> батчат (batch size / flush interval)
-> вставляют пачкой в Postgres

GET /links/{code}/stats   -> читает агрегаты из Postgres
Структура проекта
.
├── LICENSE
├── README.md
├── cmd
│   └── api
│       └── main.go
├── .env // создать свой в корне проекта
├── docker-compose.yml
├── go.mod
├── go.sum
├── internal
│   ├── config
│   │   └── config.go
│   ├── http
│   │   ├── handler
│   │   │   └── links.go
│   │   ├── httpx
│   │   │   ├── error.go
│   │   │   └── json.go
│   │   └── router.go
│   ├── repository
│   │   └── postgres
│   │       ├── db.go
│   │       └── links_repo.go
│   └── service
│       ├── errors.go
│       └── service.go
├── makefile
└── migrations
    └── 20260109150617_init.sql

API

1) Создать короткую ссылку

POST /links

curl -X POST http://localhost:8080/links \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'

Пример ответа:

{
  "code": "abc123",
  "short_url": "http://localhost:8080/abc123"
}

2) Редирект по коду

GET /{code}

curl -i http://localhost:8080/abc123

Ожидаемо: 301/302 + Location: https://example.com Параллельно создаётся событие клика (асинхронно).


3) Статистика по ссылке

GET /links/{code}/stats

curl http://localhost:8080/links/abc123/stats

Пример ответа:

{
  "code": "abc123",
  "total_clicks": 10
}

Запуск проекта (пошаговая инструкция)

Требования

  • Docker и Docker Compose
  • Go 1.21+ (для сборки)
  • goose (установите: go install github.com/pressly/goose/v3/cmd/goose@latest)

Шаг 1: Клонировать репозиторий

git clone <url-репозитория>
cd Shortener

Шаг 2: Создать .env файл

# Из примера
cp .env.example .env

Шаг 3: Запустить PostgreSQL в Docker

make up
# или
docker compose up -d

Шаг 4: Применить миграции

make migrate

Шаг 5: Собрать бинарный файл

make build

Шаг 6: Запустить приложение

make run
# или
./bin/shortener

Остановка проекта

# Остановить PostgreSQL
make down

Доступные команды Makefile

Команда Описание
make up Запустить PostgreSQL в Docker
make down Остановить PostgreSQL
make migrate Применить миграции БД
make build Собрать бинарник в папку bin/
make run Запустить приложение из бинарника

Конфигурация (ENV)

Переменная Пример / Default Описание
APP_PORT 8080 Порт HTTP сервера
DATABASE_URL postgres://postgres:postgres@localhost:5432/shortener?sslmode=disable Строка подключения к Postgres
BASE_URL http://localhost:8080 Базовый адрес для сервера

Схема работы

flowchart TB
  Client[Client / Browser / API consumer]

  subgraph App[Go service: URL Shortener API]
    Router[HTTP Router]
    Handler[Handlers]
    Service["Service layer (business logic)"]
    Repo["Repository (DB access)"]
    ClickProducer["Click Producer puts events into channel"]
    ClickChan[(chan ClickEvent)]
    Workers[Worker Pool N goroutines]
    Batcher["Batcher (size/time flush)"]
  end

  subgraph DB[PostgreSQL]
    Links[(links table)]
    Clicks[(clicks table)]
  end

  subgraph Infra[Infra]
    Compose[docker-compose]
    Migrations[goose migrations]
  end

  Client -->|POST /links| Router --> Service 
  Client -->|GET / code| Router --> Handler --> Service --> Repo 
  Handler -->|redirect 301/302| Client

  Handler -->|async click event| ClickProducer --> ClickChan
  ClickChan --> Workers --> Batcher --> Repo --> Clicks

  Compose --- App
  Compose --- DB
  Migrations --> DB
Loading

Roadmap (что можно улучшить)

  • Swagger/OpenAPI документация
  • Авторизация (API key / JWT)
  • Добавить тесты
  • Добавить логирование
  • Создать сommon libraty (pkg)

Troubleshooting

Ошибка "port 5432 already in use"

# Остановите локальный PostgreSQL
sudo systemctl stop postgresql
# Или измените порт в docker-compose.yml

Ошибка "goose: command not found"

go install github.com/pressly/goose/v3/cmd/goose@latest

Ошибка "no .env file"

cp .env.example .env

About

Сервис по сокращению ссылок с анализом кликов на языке Go

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors