-module(eventhub_app). -behaviour(application). -export([start/2, stop/1]). start(_StartType, _StartArgs) -> pg:start_link(), application:ensure_all_started(mnesia), application:ensure_all_started(cowboy), case infra_sup:start_link() of {ok, Pid} -> ok = infra_mnesia:init_tables(), ok = infra_mnesia:wait_for_tables(), connect_nodes(), start_http(), start_admin_http(), % Запускаем сборщик метрик Prometheus application:ensure_all_started(prometheus), application:ensure_all_started(prometheus_cowboy), {ok, Pid}; Error -> Error end. stop(_State) -> ok. start_http() -> Port = application:get_env(eventhub, http_port, 8080), Dispatch = cowboy_router:compile([ {'_', [ {"/metrics/[:registry]", prometheus_cowboy2_handler, []}, {"/health", handler_health, []}, {"/v1/register", handler_register, []}, {"/v1/login", handler_login, []}, {"/v1/refresh", handler_refresh, []}, {"/v1/user/me", handler_user_me, []}, {"/v1/user/bookings", handler_user_bookings, []}, {"/v1/user/reviews", handler_user_reviews, []}, {"/v1/search", handler_search, []}, {"/v1/calendars", handler_calendars, []}, {"/v1/calendars/:id", handler_calendar_by_id, []}, {"/v1/calendars/:calendar_id/events", handler_events, []}, {"/v1/events/:id", handler_event_by_id, []}, {"/v1/events/:id/occurrences", handler_event_occurrences, []}, {"/v1/events/:id/occurrences/:start_time", handler_event_occurrences, []}, {"/v1/events/:id/bookings", handler_bookings, []}, {"/v1/bookings/:id", handler_booking_by_id, []}, {"/v1/reviews", handler_reviews, []}, {"/v1/reviews/:id", handler_review_by_id, []}, {"/v1/reports", handler_reports, []}, {"/v1/tickets", handler_tickets, []}, {"/v1/subscription", handler_subscription, []}, % Админские маршруты - более конкретные ПЕРЕД общими {"/v1/admin/reports", handler_reports, []}, {"/v1/admin/reports/:id", handler_report_by_id, []}, {"/v1/admin/reviews/:id", handler_admin_reviews, []}, {"/v1/admin/banned-words", handler_banned_words, []}, {"/v1/admin/banned-words/:word", handler_banned_words, []}, {"/v1/admin/tickets/stats", handler_ticket_stats, []}, {"/v1/admin/tickets/:id", handler_ticket_by_id, []}, {"/v1/admin/tickets", handler_tickets, []}, {"/v1/admin/subscriptions", handler_admin_subscriptions, []}, {"/v1/admin/subscriptions/:id", handler_admin_subscriptions, []}, % Общий маршрут для заморозки (должен быть последним) {"/v1/admin/:target_type/:id", handler_admin_moderation, []} ]} ]), Middlewares = [ cowboy_router, cowboy_handler ], Env = #{dispatch => Dispatch}, cowboy:start_clear(http, [{port, Port}], #{ env => Env, middlewares => Middlewares }), io:format("HTTP server started on port ~p~n", [Port]). start_admin_http() -> Port = application:get_env(eventhub, admin_http_port, 8445), Dispatch = cowboy_router:compile([ {'_', [ {"/admin/health", admin_handler_health, []}, {"/admin/stats", admin_handler_stats, []}, {"/admin/users", admin_handler_users, []}, {"/admin/users/:id", admin_handler_user_by_id, []} ]} ]), Middlewares = [ cowboy_router, cowboy_handler ], Env = #{dispatch => Dispatch}, cowboy:start_clear(admin_http, [{port, Port}], #{ env => Env, middlewares => Middlewares }), io:format("Admin HTTP server started on port ~p~n", [Port]), % WebSocket для пользователей WsDispatch = cowboy_router:compile([ {'_', [{"/ws", ws_handler, []}]} ]), cowboy:start_clear(ws, [{port, 8081}], #{ env => #{dispatch => WsDispatch} }), % WebSocket для админов AdminWsDispatch = cowboy_router:compile([ {'_', [{"/admin/ws", admin_ws_handler, []}]} ]), cowboy:start_clear(admin_ws, [{port, 8446}], #{ env => #{dispatch => AdminWsDispatch} }), io:format("WebSocket started on ports 8081 (user) and 8446 (admin)~n"). connect_nodes() -> case os:getenv("JOIN_NODES") of false -> ok; NodesStr -> Nodes = [list_to_atom(string:trim(N)) || N <- string:tokens(NodesStr, ",")], lists:foreach(fun(Node) -> case net_kernel:connect_node(Node) of true -> io:format("Connected to ~s~n", [Node]); false -> io:format("ERROR: Failed to connect to ~s~n", [Node]); ignored -> ok end end, Nodes) end.