FAkka.FSI.Supervisor 1.564.101.201

There is a newer prerelease version of this package available.
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
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FAkka.FSI.Supervisor" Version="1.564.101.201" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FAkka.FSI.Supervisor" Version="1.564.101.201" />
                    
Directory.Packages.props
<PackageReference Include="FAkka.FSI.Supervisor" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FAkka.FSI.Supervisor --version 1.564.101.201
                    
#r "nuget: FAkka.FSI.Supervisor, 1.564.101.201"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FAkka.FSI.Supervisor@1.564.101.201
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FAkka.FSI.Supervisor&version=1.564.101.201
                    
Install as a Cake Addin
#tool nuget:?package=FAkka.FSI.Supervisor&version=1.564.101.201
                    
Install as a Cake Tool

Akka.FSI.Supervisor

Akka.FSI.Supervisor 是一個基於 Akka.NET 的 F# Interactive (FSI) 會話管理器。它提供了在分散式或單一行程的 Akka 系統中,安全且可擴展地執行 F# 腳本 (FsiEvaluationSession) 的機制。

程式架構 (Architecture)

本專案採用 Actor Model 設計模式,主要元件與階層如下:

  1. FsiGuardianActor (/user/fsi)

    • 負責管理並生成 FsiSupervisorActor,確保系統中有一個固定的存取點。
  2. FsiSupervisorActor (/user/fsi/supervisor)

    • 系統的核心路由與調度者。
    • 負責接收所有客戶端請求 (如 ExecCode, GetSessionInfo, 虛擬檔案操作),並將其轉發給對應的 FsiWorkerActor
    • 管理 Session 的生命週期(自動建立、重置)。
    • 整合 PcslFileSystemActor 處理分散式/持久化虛擬檔案系統 (基於 PCSL - PersistedConcurrentSortedList)。
    • 提供 ForkJoin 等高階工作階段操作機制。
  3. FsiWorkerActor (/user/fsi/supervisor/session-{name})

    • 每一個 FSI Session (例如 "default", "session-A") 對應一個專屬的 FsiWorkerActor
    • 封裝了一組 FsiSession.Handle (底層呼叫 FSharp.Compiler.ServiceFsiEvaluationSession)。
    • 確保同一個 Session 的 F# 程式碼循序執行,避免多執行緒共用狀態的問題。
    • 自動擷取標準輸出 (stdout)、標準錯誤 (stderr) 以及最後執行的結果值 (fsi_it),並將結果封裝成 ExecResult
  4. PcslFileSystem & PcslFileSystemActor

    • 提供依賴於 PCSL 的虛擬檔案層,可存放 .fsx 腳本或結果。

核心 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 動態編譯並印出結果。

注意:

  1. 執行此腳本前,請先 dotnet build Akka.FSI.Supervisor.fsproj -c Debug
  2. protobuf-net-fsharp.dll 若不在預設 probing path,請設定環境變數 PROTOBUF_FSHARP_DLL 指向實際檔案。
  3. 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.diagnosticserror 中。

README 範例已驗證的最小前置條件

以下條件下,上述 FSX 範例已在本機驗證可跑:

  • dotnet build Libs/Akka.FSI.Supervisor/Akka.FSI.Supervisor.fsproj -c Debug
  • PROTOBUF_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_DLLPersistedConcurrentSortedList.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 能 resolve
  • GetVesion timeout
  • 就直接推論成 fsi-supervisor 啟動失敗

這個推論不可靠。更穩的診斷順序是:

  1. 先確認 proc-supervisor 本身可 direct ask
  2. 再用 fresh procnode 的 fsiSupervisorPath
  3. 先試:
    • ListSessions
    • ExecCode
  4. 最後才用 GetVesion 當補充訊號

fsharp-devkit 的 deployed remote host 驗證中,曾出現過:

  • GetVesion timeout
  • 但同一個 fsi-supervisorExecCode 其實正常
  • 最終 host isolationsession isolation 都成立

因此 GetVesion timeout 只能代表該 control-plane 命令在當下沒有成功回覆,不能單獨作為 FAkka.FSI.Supervisor 整體不可用的證據。

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
Loading failed