feat: start scheduler in local development
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
# Local development without Docker Compose
|
# Local development without Docker Compose
|
||||||
|
|
||||||
This Windows-only helper runs the API, analytics worker, and frontend directly from the three sibling repositories. PostgreSQL and Redis must already be reachable locally. It does not create databases, run migrations/imports, generate credentials, edit service-owned environment files, or start Docker.
|
This Windows-only helper runs the API, analytics worker, growth-coach scheduler, and frontend directly from the three sibling repositories. PostgreSQL and Redis must already be reachable locally. It does not create databases, run migrations/imports, generate credentials, edit service-owned environment files, or start Docker.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Go and npm are on `PATH`.
|
- Go and npm are on `PATH`.
|
||||||
- PostgreSQL is reachable at `127.0.0.1:5432`.
|
- PostgreSQL is reachable at `127.0.0.1:5432`.
|
||||||
- Redis is reachable at `127.0.0.1:6379`.
|
- Redis is reachable at `127.0.0.1:6379`.
|
||||||
- The backend has `cmd/api` and `cmd/worker`, plus a protected backend-owned `.env`.
|
- The backend has `cmd/api`, `cmd/worker`, and `cmd/scheduler`, plus a protected backend-owned `.env`.
|
||||||
- The frontend has a `package.json` `dev` script and its frontend-owned local environment file.
|
- The frontend has a `package.json` `dev` script and its frontend-owned local environment file.
|
||||||
- Dependencies, migrations, the one-time importer, and demo merchant creation have already completed through their owning repositories.
|
- Dependencies, migrations, the one-time importer, and demo merchant creation have already completed through their owning repositories.
|
||||||
|
|
||||||
@@ -41,6 +41,6 @@ After `start`, open the frontend URL declared by the frontend development server
|
|||||||
|
|
||||||
The AI growth analyst is controlled by service-owned environment files; no AvalAI credential belongs in this deployment repository or in the frontend.
|
The AI growth analyst is controlled by service-owned environment files; no AvalAI credential belongs in this deployment repository or in the frontend.
|
||||||
|
|
||||||
For local deterministic verification, set `AI_GROWTH_ENABLED=true` in the ignored backend `.env` and `PUBLIC_AI_GROWTH_ENABLED=true` in the ignored frontend `.env`. With `AVALAI_API_KEY` empty, the worker must not make a provider request: it persists and serves a deterministic `PARTIAL` report instead.
|
For local verification, set `AI_COACH_ENABLED=true`, `AI_PAGE_INSIGHTS_ENABLED=true`, and `AI_GROWTH_ENABLED=true` in the ignored backend `.env`, and `PUBLIC_AI_GROWTH_ENABLED=true` in the ignored frontend `.env`. With `AVALAI_API_KEY` empty, no generation is misrepresented as a fresh AI response.
|
||||||
|
|
||||||
The backend `.env.example` is authoritative for the complete contract. The production operator must explicitly provide `AVALAI_API_KEY`, `AVALAI_MODEL`, `AI_DAILY_REQUEST_BUDGET`, and `AI_DAILY_TOKEN_BUDGET` before enabling the feature. `AVALAI_BASE_URL`, `AI_MAX_CONCURRENT`, `AI_CREATE_PER_MINUTE`, and `AI_UNCACHED_SCOPES_PER_DAY` remain configurable safety limits. Never place `AVALAI_API_KEY` in a public frontend variable.
|
The backend `.env.example` is authoritative for the complete contract. The production operator must explicitly provide `AVALAI_API_KEY`, `AVALAI_MODEL`, `AI_DAILY_REQUEST_BUDGET`, and `AI_DAILY_TOKEN_BUDGET` before enabling the feature. `AVALAI_BASE_URL`, `AI_MAX_CONCURRENT`, `AI_CREATE_PER_MINUTE`, and `AI_UNCACHED_SCOPES_PER_DAY` remain configurable safety limits. Never place `AVALAI_API_KEY` in a public frontend variable.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ function Resolve-LocalDevCommands {
|
|||||||
[Parameter(Mandatory)][string]$FrontendPath
|
[Parameter(Mandatory)][string]$FrontendPath
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach ($entrypoint in 'api', 'worker') {
|
foreach ($entrypoint in 'api', 'worker', 'scheduler') {
|
||||||
$path = Join-Path $BackendPath "cmd\$entrypoint"
|
$path = Join-Path $BackendPath "cmd\$entrypoint"
|
||||||
if (-not (Test-Path -LiteralPath $path -PathType Container)) {
|
if (-not (Test-Path -LiteralPath $path -PathType Container)) {
|
||||||
throw "Backend entrypoint cmd/$entrypoint is missing under $BackendPath"
|
throw "Backend entrypoint cmd/$entrypoint is missing under $BackendPath"
|
||||||
@@ -58,6 +58,7 @@ function Resolve-LocalDevCommands {
|
|||||||
return @{
|
return @{
|
||||||
Api = @{ FilePath = 'go'; Arguments = @('run', './cmd/api'); WorkingDirectory = $BackendPath }
|
Api = @{ FilePath = 'go'; Arguments = @('run', './cmd/api'); WorkingDirectory = $BackendPath }
|
||||||
Worker = @{ FilePath = 'go'; Arguments = @('run', './cmd/worker'); WorkingDirectory = $BackendPath }
|
Worker = @{ FilePath = 'go'; Arguments = @('run', './cmd/worker'); WorkingDirectory = $BackendPath }
|
||||||
|
Scheduler = @{ FilePath = 'go'; Arguments = @('run', './cmd/scheduler'); WorkingDirectory = $BackendPath }
|
||||||
Frontend = @{ FilePath = 'npm.cmd'; Arguments = @('run', 'dev', '--', '--host', '127.0.0.1'); WorkingDirectory = $FrontendPath }
|
Frontend = @{ FilePath = 'npm.cmd'; Arguments = @('run', 'dev', '--', '--host', '127.0.0.1'); WorkingDirectory = $FrontendPath }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,6 +189,7 @@ function Start-LocalDev {
|
|||||||
try {
|
try {
|
||||||
$started += Start-LocalProcess -Name 'api' -Command $commands.Api -Environment $backendEnvironment -LogDirectory $logDirectory
|
$started += Start-LocalProcess -Name 'api' -Command $commands.Api -Environment $backendEnvironment -LogDirectory $logDirectory
|
||||||
$started += Start-LocalProcess -Name 'worker' -Command $commands.Worker -Environment $backendEnvironment -LogDirectory $logDirectory
|
$started += Start-LocalProcess -Name 'worker' -Command $commands.Worker -Environment $backendEnvironment -LogDirectory $logDirectory
|
||||||
|
$started += Start-LocalProcess -Name 'scheduler' -Command $commands.Scheduler -Environment $backendEnvironment -LogDirectory $logDirectory
|
||||||
$started += Start-LocalProcess -Name 'frontend' -Command $commands.Frontend -Environment @{} -LogDirectory $logDirectory
|
$started += Start-LocalProcess -Name 'frontend' -Command $commands.Frontend -Environment @{} -LogDirectory $logDirectory
|
||||||
$started | ConvertTo-Json | Set-Content -LiteralPath (Get-StatePath -DeploymentPath $DeploymentPath) -Encoding utf8
|
$started | ConvertTo-Json | Set-Content -LiteralPath (Get-StatePath -DeploymentPath $DeploymentPath) -Encoding utf8
|
||||||
return $started
|
return $started
|
||||||
|
|||||||
@@ -55,12 +55,14 @@ try {
|
|||||||
$frontend = Join-Path $fixture 'frontend'
|
$frontend = Join-Path $fixture 'frontend'
|
||||||
New-Item -ItemType Directory -Path (Join-Path $backend 'cmd\api') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $backend 'cmd\api') -Force | Out-Null
|
||||||
New-Item -ItemType Directory -Path (Join-Path $backend 'cmd\worker') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $backend 'cmd\worker') -Force | Out-Null
|
||||||
|
New-Item -ItemType Directory -Path (Join-Path $backend 'cmd\scheduler') -Force | Out-Null
|
||||||
New-Item -ItemType Directory -Path $frontend -Force | Out-Null
|
New-Item -ItemType Directory -Path $frontend -Force | Out-Null
|
||||||
'{"scripts":{"dev":"vite"}}' | Set-Content -LiteralPath (Join-Path $frontend 'package.json') -Encoding utf8
|
'{"scripts":{"dev":"vite"}}' | Set-Content -LiteralPath (Join-Path $frontend 'package.json') -Encoding utf8
|
||||||
|
|
||||||
$commands = Resolve-LocalDevCommands -BackendPath $backend -FrontendPath $frontend
|
$commands = Resolve-LocalDevCommands -BackendPath $backend -FrontendPath $frontend
|
||||||
Assert-Equal './cmd/api' $commands.Api.Arguments[1] 'API command should follow the backend contract'
|
Assert-Equal './cmd/api' $commands.Api.Arguments[1] 'API command should follow the backend contract'
|
||||||
Assert-Equal './cmd/worker' $commands.Worker.Arguments[1] 'Worker command should follow the backend contract'
|
Assert-Equal './cmd/worker' $commands.Worker.Arguments[1] 'Worker command should follow the backend contract'
|
||||||
|
Assert-Equal './cmd/scheduler' $commands.Scheduler.Arguments[1] 'Scheduler command should follow the backend contract'
|
||||||
Assert-Equal 'run' $commands.Frontend.Arguments[0] 'Frontend should use its checked-in dev script'
|
Assert-Equal 'run' $commands.Frontend.Arguments[0] 'Frontend should use its checked-in dev script'
|
||||||
|
|
||||||
$stateDirectory = Join-Path $fixture '.local'
|
$stateDirectory = Join-Path $fixture '.local'
|
||||||
|
|||||||
Reference in New Issue
Block a user