Skip to content
Open
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
79 changes: 79 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,86 @@ Notes:
- `database is locked` usually means SQLite write contention, not corruption.
- For heavier multi-flow usage, move Prefect server DB to Postgres.

## Running Local Prefect Services on Windows (Task Scheduler)

To run a local Prefect server and worker as background services on Windows, you can
use PowerShell with Windows Task Scheduler and the provided templates:

- `src/echodataflow/services/deploy_prefect_server.windows.task.xml`
- `src/echodataflow/services/deploy_prefect_worker.windows.task.xml`

1. Copy and customize the service environment file:
```powershell
New-Item -ItemType Directory -Force "$HOME\.config\echodataflow"
New-Item -ItemType Directory -Force "$HOME\.local\var\log\echodataflow"

Copy-Item src\echodataflow\services\services.env.example_local `
"$HOME\.config\echodataflow\services.env"
```

2. Edit `$HOME\.config\echodataflow\services.env` as needed:
- Adjust `ECHODATAFLOW_ENV`
- Adjust `ECHODATAFLOW_HOME`
- Adjust `ECHODATAFLOW_WORKDIR`
- Adjust `ECHODATAFLOW_LOG_DIR`
- Adjust `MAMBA_BIN`
- Adjust `PREFECT_POOL`
- Adjust `PREFECT_API_URL`

3. Copy and customize the Task Scheduler XML templates:
```powershell
Copy-Item src\echodataflow\services\deploy_prefect_server.windows.task.xml `
"$HOME\.config\echodataflow\prefect-server.task.xml"

Copy-Item src\echodataflow\services\deploy_prefect_worker.windows.task.xml `
"$HOME\.config\echodataflow\prefect-worker.task.xml"
```

4. Both XML templates are self-contained and read their runtime configuration
from `$HOME\.config\echodataflow\services.env`, so they do not need separate
`deploy_prefect_*.windows.ps1` files or hard-coded repository script paths.

5. Register the scheduled tasks:
```powershell
schtasks /Create /TN "echodataflow-prefect-server" `
/XML "$HOME\.config\echodataflow\prefect-server.task.xml" /F

schtasks /Create /TN "echodataflow-prefect-worker" `
/XML "$HOME\.config\echodataflow\prefect-worker.task.xml" /F
```

6. Start the tasks:
```powershell
schtasks /Run /TN "echodataflow-prefect-server"
Start-Sleep -Seconds 10
schtasks /Run /TN "echodataflow-prefect-worker"
```

7. Check task status:
```powershell
schtasks /Query /TN "echodataflow-prefect-server" /V /FO LIST
schtasks /Query /TN "echodataflow-prefect-worker" /V /FO LIST
```

8. Verify the local Prefect server:

Open:

```text
http://127.0.0.1:4200
```

The Prefect dashboard should load, and the worker should appear online under
**Work Pools**.

9. To stop and delete the tasks:
```powershell
schtasks /End /TN "echodataflow-prefect-worker"
schtasks /End /TN "echodataflow-prefect-server"

schtasks /Delete /TN "echodataflow-prefect-worker" /F
schtasks /Delete /TN "echodataflow-prefect-server" /F
```

## License

Expand Down
37 changes: 37 additions & 0 deletions src/echodataflow/services/deploy_prefect_server.windows.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
$EnvFile = "$HOME\.config\echodataflow\services.env"

if (-not (Test-Path $EnvFile)) {
Write-Error "Missing services env file: $EnvFile"
exit 1
}

Get-Content $EnvFile | ForEach-Object {
if ($_ -match '^\s*([^#][^=]+)=(.*)$') {
$Name = $matches[1].Trim()
$Value = $matches[2].Trim()
Set-Item -Path "Env:$Name" -Value $Value
}
}

$RequiredVars = @(
"ECHODATAFLOW_ENV",
"ECHODATAFLOW_WORKDIR",
"ECHODATAFLOW_LOG_DIR",
"MAMBA_BIN"
)

foreach ($Var in $RequiredVars) {
if (-not (Get-Item -Path "Env:$Var" -ErrorAction SilentlyContinue)) {
Write-Error "Missing required environment variable: $Var"
exit 1
}
}

New-Item -ItemType Directory -Force -Path $env:ECHODATAFLOW_LOG_DIR | Out-Null

Set-Location $env:ECHODATAFLOW_WORKDIR

& $env:MAMBA_BIN run -n $env:ECHODATAFLOW_ENV `
prefect server start `
--host 127.0.0.1 `
--port 4200
95 changes: 95 additions & 0 deletions src/echodataflow/services/deploy_prefect_server.windows.task.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<!-- Task metadata -->
<RegistrationInfo>
<Description>Run the local Echodataflow Prefect server at user logon.</Description>
</RegistrationInfo>

<!-- Start at user logon -->
<Triggers>
<LogonTrigger>
<Enabled>true</Enabled>
</LogonTrigger>
</Triggers>

<!-- Run in the interactive user session -->
<Principals>
<Principal id="Author">
<LogonType>InteractiveToken</LogonType>
<RunLevel>LeastPrivilege</RunLevel>
</Principal>
</Principals>

<!-- Keep server resilient and always available -->
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>true</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
<Priority>7</Priority>
<RestartOnFailure>
<Interval>PT1M</Interval>
<Count>999</Count>
</RestartOnFailure>
</Settings>

<!-- Launch the PowerShell bootstrap logic directly -->
<Actions Context="Author">
<Exec>
<Command>powershell.exe</Command>

<!-- Inline startup script; runtime paths come from services.env -->
<Arguments><![CDATA[
-NoLogo
-NoProfile
-NonInteractive
-ExecutionPolicy Bypass
-Command "& {
$EnvFile = Join-Path $HOME '.config\echodataflow\services.env'

# Load service configuration from the standard user config location.
if (-not (Test-Path $EnvFile)) {
Write-Error ('Missing services env file: ' + $EnvFile)
exit 1
}

Get-Content $EnvFile | ForEach-Object {
if ($_ -match '^\s*([^#][^=]+)=(.*)$') {
$Name = $matches[1].Trim()
$Value = $matches[2].Trim()
Set-Item -Path ('Env:' + $Name) -Value $Value
}
}

$RequiredVars = @(
'ECHODATAFLOW_ENV'
'ECHODATAFLOW_WORKDIR'
'ECHODATAFLOW_LOG_DIR'
'MAMBA_BIN'
)

foreach ($Var in $RequiredVars) {
if (-not (Get-Item -Path ('Env:' + $Var) -ErrorAction SilentlyContinue)) {
Write-Error ('Missing required environment variable: ' + $Var)
exit 1
}
}

New-Item -ItemType Directory -Force -Path $env:ECHODATAFLOW_LOG_DIR | Out-Null
Set-Location $env:ECHODATAFLOW_WORKDIR

& $env:MAMBA_BIN run -n $env:ECHODATAFLOW_ENV `
prefect server start `
--host 127.0.0.1 `
--port 4200
}"
]]></Arguments>
</Exec>
</Actions>
</Task>
37 changes: 37 additions & 0 deletions src/echodataflow/services/deploy_prefect_worker.windows.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
$EnvFile = "$HOME\.config\echodataflow\services.env"

if (-not (Test-Path $EnvFile)) {
Write-Error "Missing services env file: $EnvFile"
exit 1
}

Get-Content $EnvFile | ForEach-Object {
if ($_ -match '^\s*([^#][^=]+)=(.*)$') {
$Name = $matches[1].Trim()
$Value = $matches[2].Trim()
Set-Item -Path "Env:$Name" -Value $Value
}
}

$RequiredVars = @(
"ECHODATAFLOW_ENV",
"ECHODATAFLOW_WORKDIR",
"ECHODATAFLOW_LOG_DIR",
"MAMBA_BIN",
"PREFECT_POOL"
)

foreach ($Var in $RequiredVars) {
if (-not (Get-Item -Path "Env:$Var" -ErrorAction SilentlyContinue)) {
Write-Error "Missing required environment variable: $Var"
exit 1
}
}

New-Item -ItemType Directory -Force -Path $env:ECHODATAFLOW_LOG_DIR | Out-Null

Set-Location $env:ECHODATAFLOW_WORKDIR

& $env:MAMBA_BIN run -n $env:ECHODATAFLOW_ENV `
prefect worker start `
--pool $env:PREFECT_POOL
96 changes: 96 additions & 0 deletions src/echodataflow/services/deploy_prefect_worker.windows.task.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<!-- Task metadata -->
<RegistrationInfo>
<Description>Run the local Echodataflow Prefect worker at user logon.</Description>
</RegistrationInfo>

<!-- Start at user logon, after a short delay so the server can start first -->
<Triggers>
<LogonTrigger>
<Enabled>true</Enabled>
<Delay>PT1M</Delay>
</LogonTrigger>
</Triggers>

<!-- Run in the interactive user session -->
<Principals>
<Principal id="Author">
<LogonType>InteractiveToken</LogonType>
<RunLevel>LeastPrivilege</RunLevel>
</Principal>
</Principals>

<!-- Keep worker resilient and always available -->
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>true</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
<Priority>7</Priority>
<RestartOnFailure>
<Interval>PT1M</Interval>
<Count>999</Count>
</RestartOnFailure>
</Settings>

<!-- Launch the PowerShell bootstrap logic directly -->
<Actions Context="Author">
<Exec>
<Command>powershell.exe</Command>

<!-- Inline startup script; runtime paths come from services.env -->
<Arguments><![CDATA[
-NoLogo
-NoProfile
-NonInteractive
-ExecutionPolicy Bypass
-Command "& {
$EnvFile = Join-Path $HOME '.config\echodataflow\services.env'

# Load service configuration from the standard user config location.
if (-not (Test-Path $EnvFile)) {
Write-Error ('Missing services env file: ' + $EnvFile)
exit 1
}

Get-Content $EnvFile | ForEach-Object {
if ($_ -match '^\s*([^#][^=]+)=(.*)$') {
$Name = $matches[1].Trim()
$Value = $matches[2].Trim()
Set-Item -Path ('Env:' + $Name) -Value $Value
}
}

$RequiredVars = @(
'ECHODATAFLOW_ENV'
'ECHODATAFLOW_WORKDIR'
'ECHODATAFLOW_LOG_DIR'
'MAMBA_BIN'
'PREFECT_POOL'
)

foreach ($Var in $RequiredVars) {
if (-not (Get-Item -Path ('Env:' + $Var) -ErrorAction SilentlyContinue)) {
Write-Error ('Missing required environment variable: ' + $Var)
exit 1
}
}

New-Item -ItemType Directory -Force -Path $env:ECHODATAFLOW_LOG_DIR | Out-Null
Set-Location $env:ECHODATAFLOW_WORKDIR

& $env:MAMBA_BIN run -n $env:ECHODATAFLOW_ENV `
prefect worker start `
--pool $env:PREFECT_POOL
}"
]]></Arguments>
</Exec>
</Actions>
</Task>