それ、F#でやってみました - Microsoft Garnetの起動とアクセス
Microsoftが開発しているRedis互換の高速キャッシュストアGarnetのサーバ起動とクライアントでのアクセスをF#でやってみました。
環境は以下の通りです
- .NET8.0
- Garnet 1.0.4
- git
- Linux / Windows (バス区切りの記号などは適宜読み替えてください)
Garnetのビルド
Garnetのビルドは公式ドキュメント[1]を参考にして以下のコマンドで行いました。
git clone git@github.com:microsoft/garnet.git -b v1.0.4
cd garnet
dotnet restore
dotnet build -c Release
Getnetサーバの起動
Gatnetサーバをコマンドで起動するときは以下を実行しました。
(pwd: garnet)
cd main/GarnetServer
dotnet run -c Release -f net8.0
サーバが正常に起動すると以下が表示されます。停止はCtrl+C
でできました。
_________
/_||___||_\ Garnet 1.0.4 64 bit; standalone mode
'. \ / .' Port: 3278
'.\ /.' https://aka.ms/GetGarnet
'.'
F#でのサーバの起動と停止は以下のようにしました。Nugetに接続できればGarnetServer
クラスを生成してStart
メソッドを実行するだけでした。
#r "nuget: Microsoft.Garnet"
open Garnet // サーバ用
// サーバ起動
let server = new GarnetServer([||])
server.Start()
// ... クライアントで接続 ...
// サーバ停止、オブジェクト削除
server.Dispose()
Garnetクライアントによるサーバ接続
GarnetはRedis互換のため、redis-cliによる接続もできますが、F#からでもGarnetClient
クラスでできます。なお、以下はC#で書かれたGarnetに含まれているサンプルプログラム[2]を参考にしていますが、awaitの部分はasync式やAsyncクラスなどは使用せず、Taskクラスのメソッドやプロパティを使用しています。
Garnetサーバへの接続はConnectAsync
、切断はQuitAsync
の各メソッドで行いました。
#r "nuget: Microsoft.Garnet"
open Garnet.client // クライアント用
// クライアント初期設定
let db = new GarnetClient("127.0.0.1", 3278) // デフォルト設定
db.ConnectAsync().Wait() // Garnetサーバに接続
printfn "Garnet Connected: %A" db.IsConnected // 接続できたらtrue
// ... データの登録、削除など ...
db.QuitAsync().Wait() // サーバから切断
Garnetに文字列を登録
文字列の登録はStringSetAsync
、取得はStringGetAsync
で行いました。
db.StringSetAsync("key1", "MSGarnet").Wait() // ~.Resultの値は正常ならtrue
printfn "key1 = %A" (db.StringGetAsync("key1").Result)
APIを実行
GarnetのAPIはExecuteForLongResultAsync
とExecuteForStringResultAsync
メソッドで実行しました。戻る値によってメソッドが異なります。APIの引数は配列で設定しています。
printfn "EXISTS key1 = %A" (db.ExecuteForLongResultAsync("EXISTS", [| "key1" |]).Result) // 1L
printfn "RENAME key1 newkey1: %A" (db.ExecuteForStringResultAsync("RENAME", [| "key1"; "newkey1" |]).Result) // "OK"
データの削除
データの削除はKeyDeleteAsync
メソッドで行いました。
printfn "key1 delete"
db.KeyDeleteAsync("key1").Wait() // ~.Resultの値は正常ならtrue
数値データの増減
数値データを1増やすときはStringIncrement
、1減らすときはStringDecrement
メソッドで行いました。
db.StringSetAsync("key2", "100").Wait() // ~.Resultの値は正常ならtrue
printfn "key2 = %A" (db.StringGetAsync("key2").Result)
// 数値データの増減
printfn "key2 incr. = %A" (db.StringIncrement("key2").Result)
printfn "key2 decr. = %A" (db.StringDecrement("key2").Result)
ソース一覧
//
// F#でMicrosoft Garnetのサーバ起動とクライアントでのアクセス
// dotnet fsi garnet_example.fsx
//
#r "nuget: Microsoft.Garnet"
open System
open System.Text
open Garnet // サーバ用
open Garnet.client // クライアント用
// サーバ起動
let server = new GarnetServer([||])
server.Start()
// クライアント初期設定
let db = new GarnetClient("127.0.0.1", 3278)
// サーバに接続
printfn "client connect"
db.ConnectAsync().Wait() // Garnetサーバに接続
printfn "Garnet Connected: %A" db.IsConnected // 接続できたらtrue
// Ping
printfn "Ping: %A" (db.PingAsync().Result)
// 文字列データの登録と読み込み
printfn "----------"
printfn "key1 set"
db.StringSetAsync("key1", "MSGarnet").Wait() // ~.Resultの値は正常ならtrue
printfn "key1 = %A" (db.StringGetAsync("key1").Result)
// データの存在を確認
printfn "EXISTS key1 = %A" (db.ExecuteForLongResultAsync("EXISTS", [| "key1" |]).Result) // 1L
printfn "RENAME key1 newkey1: %A" (db.ExecuteForStringResultAsync("RENAME", [| "key1"; "newkey1" |]).Result) // "OK"
printfn "RENAME newkey1 key1: %A" (db.ExecuteForStringResultAsync("RENAME", [| "newkey1"; "key1" |]).Result) // "OK"
// データの削除
printfn "key1 delete"
db.KeyDeleteAsync("key1").Wait() // ~.Resultの値は正常ならtrue
printfn "EXISTS key1 = %A" (db.ExecuteForLongResultAsync("EXISTS", [| "key1" |]).Result) // 0L
// 数値データの登録と読み込み
printfn "----------"
printfn "key2 set"
db.StringSetAsync("key2", "100").Wait() // ~.Resultの値は正常ならtrue
printfn "key2 = %A" (db.StringGetAsync("key2").Result)
// 数値データの増減
printfn "key2 incr. = %A" (db.StringIncrement("key2").Result)
printfn "key2 incr. = %A" (db.StringIncrement("key2").Result)
printfn "key2 decr. = %A" (db.StringDecrement("key2").Result)
printfn "key2 decr. = %A" (db.StringDecrement("key2").Result)
// データの削除
printfn "key2 delete"
db.KeyDeleteAsync("key2").Wait() // ~.Resultの値は正常ならtrue
// System.Memoryによるデータの登録
printfn "----------"
printfn "key3 set"
let key = new Memory<byte>(Array.zeroCreate 4)
Encoding.UTF8.GetBytes("key3".AsSpan(), key.Span)
let value = new Memory<byte>(Array.zeroCreate 8)
Encoding.UTF8.GetBytes("MSGarnet".AsSpan(), value.Span)
db.StringSetAsync(key, value).Wait()
// System.Memoryによるデータの取得
let result = db.StringGetAsMemoryAsync(key).Result
printfn "%s = %s" (Encoding.UTF8.GetString(key.Span)) (Encoding.UTF8.GetString(result.Span))
// データの削除
printfn "key3 delete"
db.KeyDeleteAsync("key3").Wait() // ~.Resultの値は正常ならtrue
// サーバから切断
printfn "----------"
printfn "client quit"
db.QuitAsync().Wait()
// サーバ停止、オブジェクト削除
server.Dispose()
client connect
Garnet Connected: true
Ping: "PONG"
----------
key1 set
key1 = "MSGarnet"
EXISTS key1 = 1L
RENAME key1 newkey1: "OK"
RENAME newkey1 key1: "OK"
key1 delete
EXISTS key1 = 0L
----------
key2 set
key2 = "100"
key2 incr. = 101L
key2 incr. = 102L
key2 decr. = 101L
key2 decr. = 100L
key2 delete
----------
key3 set
key3 = MSGarnet
key3 delete
----------
client quit
GarnetのgithubリポジトリにはGarnetServer
やGarnetClient
以外にもさまざまなクラスやメソッドがあるようです。いろいろと探ってみてください。
Discussion