Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,11 @@ ORDER_DB_PORT=5434
NOTIFICATION_DB_PORT=5435

# Application Secrets
APP_SECRET=your_microservices_secret_here
APP_SECRET=your_microservices_secret_here


# RabbitMQ
RABBITMQ_USER=guest
RABBITMQ_PASSWORD=guest
RABBITMQ_HOST=rabbitmq
RABBITMQ_PORT=5672
26 changes: 24 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@ services:
- order-service
- notification-service

rabbitmq:
image: rabbitmq:3-management
container_name: rabbitmq
environment:
RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER:-guest}
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD:-guest}
ports:
- "15672:15672" # Web UI
- "5672:5672" # AMQP port
healthcheck:
test: [ "CMD", "rabbitmqctl", "status" ]
interval: 30s
timeout: 10s
retries: 3

user-service:
build: ./services/user-service
container_name: user-service
Expand All @@ -20,10 +35,13 @@ services:
- ./services/user-service/.env
volumes:
- ./services/user-service:/var/www/html
- ./shared:/var/www/html/shared
environment:
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@user-db:5432/${USER_DB_NAME}?serverVersion=15&charset=utf8
- MESSENGER_TRANSPORT_DSN=amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@rabbitmq:5672/%2f/messages
depends_on:
- user-db
- rabbitmq
expose:
- "9000"

Expand All @@ -32,9 +50,10 @@ services:
container_name: order-service
env_file:
- .env
- ./services/user-service/.env
- ./services/order-service/.env
volumes:
- ./services/order-service:/var/www/html
- ./shared:/var/www/html/shared
environment:
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@order-db:5432/${ORDER_DB_NAME}?serverVersion=15&charset=utf8
depends_on:
Expand All @@ -47,13 +66,16 @@ services:
container_name: notification-service
env_file:
- .env
- ./services/user-service/.env
- ./services/notification-service/.env
volumes:
- ./services/notification-service:/var/www/html
- ./shared:/var/www/html/shared
environment:
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@notification-db:5432/${NOTIFICATION_DB_NAME}?serverVersion=15&charset=utf8
- MESSENGER_TRANSPORT_DSN=amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@rabbitmq:5672/%2f/messages
depends_on:
- notification-db
- rabbitmq
expose:
- "9000"

Expand Down
25 changes: 24 additions & 1 deletion makefile
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,29 @@ lint:
fi; \
done

## Install dependencies for a specific service inside container
composer-install:
@if [ -z "$(service)" ]; then \
echo "❌ Usage: make composer-install service=<service_name>"; \
echo "Example: make composer-install service=user-service"; \
exit 1; \
fi
@echo "📦 Installing dependencies for $(service)..."
@docker compose exec $(service) composer install --no-interaction --prefer-dist --optimize-autoloader
@echo "✅ Dependencies installed for $(service)."

## Update dependencies for a specific service inside container
composer-update:
@if [ -z "$(service)" ]; then \
echo "❌ Usage: make composer-update service=<service_name>"; \
echo "Example: make composer-update service=order-service"; \
exit 1; \
fi
@echo "📦 Updating dependencies for $(service)..."
@docker compose exec $(service) composer update --no-interaction --prefer-dist --optimize-autoloader
@echo "✅ Dependencies updated for $(service)."


## Show this help
help:
@echo "Available commands:"
Expand All @@ -81,4 +104,4 @@ help:
@echo " make update - Update dependencies in all services"
@echo " make test - Run test for services"
@echo " make lint - Check services with PhpStan"
@echo " make help - Show this help"
@echo " make help - Show this help"
13 changes: 9 additions & 4 deletions services/notification-service/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@

FROM php:8.3-fpm

# Install dependencies
RUN apt-get update && apt-get install -y zip unzip git libpq-dev \
# Install system dependencies
RUN apt-get update && apt-get install -y \
zip unzip git libpq-dev \
&& docker-php-ext-install pdo pdo_pgsql

# Install RabbitMQ dependencies and AMQP extension
RUN apt-get update && apt-get install -y librabbitmq-dev \
&& pecl install amqp \
&& docker-php-ext-enable amqp

# Install composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

# Copy app
COPY . .

# Install PHP deps
RUN composer install --no-interaction --prefer-dist --no-scripts || true

Expand All @@ -20,4 +26,3 @@ RUN chown -R www-data:www-data /var/www/html
EXPOSE 9000

CMD ["php-fpm", "-F", "-R"]

5 changes: 4 additions & 1 deletion services/notification-service/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
"php": ">=8.2",
"ext-ctype": "*",
"ext-iconv": "*",
"microservices/shared-contracts": "1.*",
"symfony/amqp-messenger": "7.3.*",
"symfony/console": "7.3.*",
"symfony/dotenv": "7.3.*",
"symfony/flex": "^2.8.2",
"symfony/framework-bundle": "7.3.*",
"symfony/messenger": "7.3.*",
"symfony/runtime": "7.3.*",
"symfony/yaml": "7.3.*"
},
Expand Down Expand Up @@ -64,7 +67,7 @@
"repositories": [
{
"type": "path",
"url": "../../shared",
"url": "./shared",
"options": {
"symlink": false
}
Expand Down
31 changes: 31 additions & 0 deletions services/notification-service/config/packages/messenger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
framework:
messenger:
# Uncomment this (and the failed transport below) to send failed messages to this transport for later handling.
# failure_transport: failed

transports:
# https://symfony.com/doc/current/messenger.html#transport-configuration
# async: '%env(MESSENGER_TRANSPORT_DSN)%'
# failed: 'doctrine://default?queue_name=failed'
# sync: 'sync://'
async:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
options:
exchange:
name: user_events
type: direct
queues:
user_registered: ~

routing:
# Route your messages to the transports
# 'App\Message\YourMessage': async
'Microservices\SharedEvents\UserRegisteredEvent': async

# when@test:
# framework:
# messenger:
# transports:
# # replace with your transport name here (e.g., my_transport: 'in-memory://')
# # For more Messenger testing tools, see https://github.com/zenstruck/messenger-test
# async: 'in-memory://'
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace App\MessageHandler;

use Microservices\SharedEvents\UserRegisteredEvent;
use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;

#[AsMessageHandler]
class UserRegisteredEventHandler
{
public function __construct(
private LoggerInterface $logger,
) {}

public function __invoke(UserRegisteredEvent $event): void
{
$this->logger->info('🎉 User registered event received', [
'eventId' => $event->eventId,
'userId' => $event->userId,
'email' => $event->email,
'firstName' => $event->firstName,
'lastName' => $event->lastName,
]);

try {
// Имитация отправки приветственного email
$this->sendWelcomeEmail($event->email, $event->firstName, $event->lastName);

// Имитация отправки push-уведомления
$this->sendPushNotification($event->userId, $event->firstName);

$this->logger->info('✅ Notifications sent successfully for user', [
'userId' => $event->userId,
'email' => $event->email,
]);

} catch (\Exception $e) {
$this->logger->error('❌ Failed to send notifications', [
'userId' => $event->userId,
'error' => $e->getMessage(),
]);
}
}

private function sendWelcomeEmail(string $email, string $firstName, string $lastName): void
{
// Имитация отправки email
$this->logger->info("📧 Sending welcome email to: {$email}");
$this->logger->info("👋 Dear {$firstName} {$lastName}, welcome to our platform!");

// Заглушка для реальной отправки email
// sleep(1);
}

private function sendPushNotification(string $userId, string $firstName): void
{
// Имитация отправки push-уведомления
$this->logger->info("📱 Sending push notification to user: {$userId}");
$this->logger->info("🔔 Welcome {$firstName}! Your account has been created successfully.");

// Заглушка для реальной отправки push
// sleep(1);
}
}
12 changes: 12 additions & 0 deletions services/notification-service/symfony.lock
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@
".editorconfig"
]
},
"symfony/messenger": {
"version": "7.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.0",
"ref": "ba1ac4e919baba5644d31b57a3284d6ba12d52ee"
},
"files": [
"config/packages/messenger.yaml"
]
},
"symfony/routing": {
"version": "7.3",
"recipe": {
Expand Down
2 changes: 1 addition & 1 deletion services/order-service/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"repositories": [
{
"type": "path",
"url": "../../shared",
"url": "./shared",
"options": {
"symlink": false
}
Expand Down
12 changes: 8 additions & 4 deletions services/user-service/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@

FROM php:8.3-fpm

# Install dependencies
RUN apt-get update && apt-get install -y zip unzip git libpq-dev \
# Install system dependencies
RUN apt-get update && apt-get install -y \
zip unzip git libpq-dev \
&& docker-php-ext-install pdo pdo_pgsql

# Install RabbitMQ dependencies and AMQP extension
RUN apt-get update && apt-get install -y librabbitmq-dev \
&& pecl install amqp \
&& docker-php-ext-enable amqp

# Install composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

Expand All @@ -21,4 +26,3 @@ RUN chown -R www-data:www-data /var/www/html
EXPOSE 9000

CMD ["php-fpm", "-F", "-R"]

4 changes: 3 additions & 1 deletion services/user-service/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
"doctrine/doctrine-migrations-bundle": "^3.5",
"doctrine/orm": "^3.5",
"microservices/shared-contracts": "1.*",
"symfony/amqp-messenger": "7.3.*",
"symfony/console": "7.3.*",
"symfony/dotenv": "7.3.*",
"symfony/flex": "^2.8.2",
"symfony/framework-bundle": "7.3.*",
"symfony/messenger": "7.3.*",
"symfony/runtime": "7.3.*",
"symfony/security-bundle": "7.3.*",
"symfony/yaml": "7.3.*"
Expand Down Expand Up @@ -73,7 +75,7 @@
"repositories": [
{
"type": "path",
"url": "../../shared",
"url": "./shared",
"options": {
"symlink": false
}
Expand Down
31 changes: 31 additions & 0 deletions services/user-service/config/packages/messenger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
framework:
messenger:
# Uncomment this (and the failed transport below) to send failed messages to this transport for later handling.
# failure_transport: failed

transports:
# https://symfony.com/doc/current/messenger.html#transport-configuration
# async: '%env(MESSENGER_TRANSPORT_DSN)%'
# failed: 'doctrine://default?queue_name=failed'
# sync: 'sync://'
async:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
options:
exchange:
name: user_events
type: direct
queues:
user_registered: ~

routing:
# Route your messages to the transports
# 'App\Message\YourMessage': async
'Microservices\SharedEvents\UserRegisteredEvent': async

# when@test:
# framework:
# messenger:
# transports:
# # replace with your transport name here (e.g., my_transport: 'in-memory://')
# # For more Messenger testing tools, see https://github.com/zenstruck/messenger-test
# async: 'in-memory://'
Loading
Loading