FAkka.FSI.Supervisor
1.564.101.201
See the version list below for details.
dotnet add package FAkka.FSI.Supervisor --version 1.564.101.201
NuGet\Install-Package FAkka.FSI.Supervisor -Version 1.564.101.201
<PackageReference Include="FAkka.FSI.Supervisor" Version="1.564.101.201" />
<PackageVersion Include="FAkka.FSI.Supervisor" Version="1.564.101.201" />
<PackageReference Include="FAkka.FSI.Supervisor" />
paket add FAkka.FSI.Supervisor --version 1.564.101.201
#r "nuget: FAkka.FSI.Supervisor, 1.564.101.201"
#:package FAkka.FSI.Supervisor@1.564.101.201
#addin nuget:?package=FAkka.FSI.Supervisor&version=1.564.101.201
#tool nuget:?package=FAkka.FSI.Supervisor&version=1.564.101.201
Akka.FSI.Supervisor
Akka.FSI.Supervisor 是一個基於 Akka.NET 的 F# Interactive (FSI) 會話管理器。它提供了在分散式或單一行程的 Akka 系統中,安全且可擴展地執行 F# 腳本 (FsiEvaluationSession) 的機制。
程式架構 (Architecture)
本專案採用 Actor Model 設計模式,主要元件與階層如下:
FsiGuardianActor(/user/fsi)- 負責管理並生成
FsiSupervisorActor,確保系統中有一個固定的存取點。
- 負責管理並生成
FsiSupervisorActor(/user/fsi/supervisor)- 系統的核心路由與調度者。
- 負責接收所有客戶端請求 (如
ExecCode,GetSessionInfo, 虛擬檔案操作),並將其轉發給對應的FsiWorkerActor。 - 管理 Session 的生命週期(自動建立、重置)。
- 整合
PcslFileSystemActor處理分散式/持久化虛擬檔案系統 (基於 PCSL - PersistedConcurrentSortedList)。 - 提供
Fork、Join等高階工作階段操作機制。
FsiWorkerActor(/user/fsi/supervisor/session-{name})- 每一個 FSI Session (例如 "default", "session-A") 對應一個專屬的
FsiWorkerActor。 - 封裝了一組
FsiSession.Handle(底層呼叫FSharp.Compiler.Service的FsiEvaluationSession)。 - 確保同一個 Session 的 F# 程式碼循序執行,避免多執行緒共用狀態的問題。
- 自動擷取標準輸出 (stdout)、標準錯誤 (stderr) 以及最後執行的結果值 (
fsi_it),並將結果封裝成ExecResult。
- 每一個 FSI Session (例如 "default", "session-A") 對應一個專屬的
PcslFileSystem&PcslFileSystemActor- 提供依賴於 PCSL 的虛擬檔案層,可存放
.fsx腳本或結果。
- 提供依賴於 PCSL 的虛擬檔案層,可存放
核心 API 與介面
對外溝通主要透過 Akka.NET 的訊息傳遞 (Message Passing) 或使用 AkkaFsiBootstrap 提供的 Helper 模組。
AkkaFsiBootstrap (位於 Api.fs)
提供啟動、初始化 Supervisor 與封裝好的非同步函數。
EnsureSupervisor(system: ActorSystem): 在指定的 ActorSystem 啟動 Guardian 與 Supervisor。GetSupervisor(system: ActorSystem): 取得 Supervisor 的IActorRef。ExecJson(supervisor: IActorRef, json: string): 接收 JSON 格式的ExecCode請求,並非同步回傳ExecResult的 JSON 字串。GetSessionInfoJson(supervisor: IActorRef, session: string): 取得特定 Session 的狀態。
主要訊息協定 (Contracts)
(定義於 Akka.FSI.Contracts,序列化採用 JsonCodec)
ExecCode/ExecCodeJson: 提交程式碼執行請求。session: 目標 Session 名稱 (預設為 "default")。code: 要執行的 F# 程式碼字串。refs/loads: 需要載入的參考 dll (#r) 或腳本 (#load)。
ExecResult: 執行完成的結果。ok: 執行是否成功。resultJson: 執行的最後回傳值 (it)。stdout/stderr: 輸出。diagnostics: 編譯/執行階段的錯誤或警告。
E2E 範例腳本 (FSX)
以下示範如何在一個獨立的 .fsx 腳本中,建立 ActorSystem、掛載 Supervisor,並送出一段 F# 程式碼給 FSI 動態編譯並印出結果。
注意:
- 執行此腳本前,請先
dotnet build Akka.FSI.Supervisor.fsproj -c Debug。protobuf-net-fsharp.dll若不在預設 probing path,請設定環境變數PROTOBUF_FSHARP_DLL指向實際檔案。- README 內的
bin/Debug/net10.0/...路徑只是示意;若你是在 repo 外執行.fsx,請改成實際輸出路徑。
// load_fsi.fsx
#r "nuget: Akka, 1.5.62"
#r "nuget: FSharp.Compiler.Service, 43.12.201"
// 請將 repoRoot 改成你的 PulseTrade.fs 實際路徑
let repoRoot = "/absolute/path/to/PulseTrade.fs"
let outDir = repoRoot + "/Libs/Akka.FSI.Supervisor/bin/Debug/net10.0"
#r outDir + "/FAkka.Fsi.Contracts.dll"
#r outDir + "/Akka.FSI.Supervisor.dll"
#r outDir + "/PersistedConcurrentSortedList.IFileSystem.dll"
open System
open System.Text.Json
open Akka.Actor
open Akka.FSI.Contracts
open Akka.FSI.Supervisor
// 1. 視需要顯式指定 protobuf-net-fsharp.dll 路徑
Environment.SetEnvironmentVariable(
"PROTOBUF_FSHARP_DLL",
outDir + "/protobuf-net-fsharp.dll"
)
// 2. 建立 Akka ActorSystem
let system = ActorSystem.Create("TestFsiSystem")
// 3. 初始化並確保 Supervisor 啟動
let supervisorRef = AkkaFsiBootstrap.EnsureSupervisor(system)
printfn "Supervisor is ready: %A" supervisorRef
// 4. 準備要丟給 FSI 動態執行的程式碼
// 這段程式碼會被送進 FsiWorkerActor 解析
let codeToExecute = """
let add a b = a + b
let result = add 100 50
printfn "Inside FSI: add function evaluated!"
result // 這是 fsi_it, 會被捕捉回傳
"""
// 建立 ExecCode 請求
let execRequest =
{
id = Guid.NewGuid().ToString("N")
session = "session-1" // 指定獨立的 session
code = codeToExecute
refs = []
loads = []
args = None
timeoutMs = Some 10000
captureStdout = Some true
}
// 將 Request 序列化為 JSON (模擬真實 API 呼叫情境)
let jsonRequest = JsonCodec.serialize execRequest
async {
printfn "Sending ExecRequest..."
// 5. 透過 Api.fs 的 Helper 發送請求
let! jsonResponse = AkkaFsiBootstrap.ExecJson supervisorRef jsonRequest
// 6. 反序列化並檢視結果
let result = JsonCodec.deserialize<ExecResult> jsonResponse
printfn "--- Execution Result ---"
printfn "Is OK: %b" result.ok
printfn "Stdout: %s" result.stdout
printfn "Stderr: %s" result.stderr
printfn "Captured It Value (JSON): %A" result.resultJson
// 7. 查詢 Session 狀態
let! sessionInfoJson = AkkaFsiBootstrap.GetSessionInfoJson supervisorRef "session-1"
let sessionInfo = JsonCodec.deserialize<SessionInfo> sessionInfoJson
printfn "Session Status: %s" sessionInfo.status
// 清理資源
system.Terminate() |> ignore
} |> Async.RunSynchronously
system.WhenTerminated.Wait()
printfn "System terminated."
開發與執行規範
- 建置 (Build): 使用
dotnet build Akka.FSI.Supervisor.fsproj。 - 依賴管理: 若需更新套件,請務必使用
dotnet-outdated-tool,嚴禁手動寫 python 腳本替換版本號。 - 環境變數
PROTOBUF_FSHARP_DLL: 在Supervisor.fs(ProtoBufInit模組) 中,系統會嘗試載入protobuf-net-fsharp.dll。這段初始化的目的不是 Akka remoting,也不是GetVesion/ListSessions這類 control-plane 訊息,而是為了本專案同時整合的 PCSL (PersistedConcurrentSortedList) + protobuf 儲存路徑:FsiSupervisorActor啟動時會建立PcslFileSystemActor- 接著會執行
PcslFileSystem.install - PCSL/protobuf runtime model 若沒有先註冊
F# unit,後續儲存/快照/結果相關操作可能在執行期失敗 - 因此
ProtoBufInit.ensureUnitSerializer()是 PCSL/protobuf 初始化需求,不是 Akka remoting 基本需求 - 若 dll 不在預設 probing path,下列環境變數必須指到正確檔案,否則 supervisor 可能能啟動,但 PCSL/protobuf 能力不完整
- Logging 與除錯: Actor 內部均有繼承自 Akka 的
Logging.GetLogger,若 FSI 執行過程中拋出例外,將會包含在ExecResult.diagnostics或error中。
README 範例已驗證的最小前置條件
以下條件下,上述 FSX 範例已在本機驗證可跑:
dotnet build Libs/Akka.FSI.Supervisor/Akka.FSI.Supervisor.fsproj -c DebugPROTOBUF_FSHARP_DLL=<repo>/Libs/Akka.FSI.Supervisor/bin/Debug/net10.0/protobuf-net-fsharp.dll#r指向:.../FAkka.Fsi.Contracts.dll.../Akka.FSI.Supervisor.dll.../PersistedConcurrentSortedList.IFileSystem.dll
若少了 PROTOBUF_FSHARP_DLL 或 PersistedConcurrentSortedList.IFileSystem.dll 指到錯誤路徑,影響通常是:
Akka.Remote本身未必立刻失敗- 但
FsiSupervisorActor啟動中的 PCSL/protobuf 初始化可能失敗 - 進而導致 supervisor actor 無法完整啟動,或後續 checkpoint / storage / filesystem 行為異常
因此在 fsharp-devkit 這類把 FAkka.FSI.Supervisor 當成 remote host 使用的場景中,PROTOBUF_FSHARP_DLL 仍屬部署前置條件,不應省略。
部署診斷注意事項
FAkka.FSI.Supervisor 在 remote host 場景下,常見誤判是:
fsiSupervisorPath能 resolveGetVesiontimeout- 就直接推論成
fsi-supervisor啟動失敗
這個推論不可靠。更穩的診斷順序是:
- 先確認
proc-supervisor本身可 direct ask - 再用 fresh procnode 的
fsiSupervisorPath - 先試:
ListSessionsExecCode
- 最後才用
GetVesion當補充訊號
在 fsharp-devkit 的 deployed remote host 驗證中,曾出現過:
GetVesiontimeout- 但同一個
fsi-supervisor對ExecCode其實正常 - 最終
host isolation與session isolation都成立
因此 GetVesion timeout 只能代表該 control-plane 命令在當下沒有成功回覆,不能單獨作為 FAkka.FSI.Supervisor 整體不可用的證據。
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Akka (>= 1.5.64)
- Akka.Cluster (>= 1.5.64)
- Akka.Remote (>= 1.5.64)
- FAkka.Fsi.Contracts (>= 10.1.201.4)
- FSharp.Compiler.Service (>= 43.12.201)
- FSharp.Core (>= 10.1.201)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
- PersistedConcurrentSortedList (>= 10.1.201.2)
- PersistedConcurrentSortedList.IFileSystem (>= 10.1.201)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on FAkka.FSI.Supervisor:
| Package | Downloads |
|---|---|
|
FAkka.Proc.Supervisor
Package Description |
|
|
PulseTrade.Shared.fs
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.564.101.203-win5 | 151 | 5/3/2026 |
| 1.564.101.203-win4 | 96 | 5/3/2026 |
| 1.564.101.203-win3 | 102 | 5/3/2026 |
| 1.564.101.203-win2 | 92 | 5/3/2026 |
| 1.564.101.203-win1 | 97 | 5/3/2026 |
| 1.564.101.201 | 120 | 4/7/2026 |
| 1.564.101.201-win7 | 114 | 4/19/2026 |
| 1.564.101.201-win6 | 103 | 4/19/2026 |
| 1.564.101.201-win5 | 100 | 4/19/2026 |
| 1.564.101.201-win4 | 114 | 4/18/2026 |
| 1.564.101.201-win3 | 97 | 4/18/2026 |
| 1.564.101.201-win2 | 111 | 4/16/2026 |
| 1.564.101.201-win1 | 104 | 4/12/2026 |
| 1.562.101.201-dgx.21 | 68 | 3/30/2026 |
| 1.562.101.201-dgx.20 | 56 | 3/30/2026 |
| 1.562.101.201-dgx.19 | 53 | 3/30/2026 |
| 1.562.101.201-dgx.18 | 61 | 3/30/2026 |
| 1.562.101.201-dgx.17 | 59 | 3/30/2026 |
| 1.562.101.201-dgx.16 | 56 | 3/30/2026 |
| 1.562.101.201-dgx.15 | 54 | 3/29/2026 |