feat: Add basic key-value store example
- Added a client and server for a simple key-value store. - Improved documentation with client and server usage examples. - Created client and server implementations using the V language.
This commit is contained in:
23
examples/data/ourdb_client.vsh
Executable file
23
examples/data/ourdb_client.vsh
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
// Please note that before running this script you need to run the server first
|
||||||
|
// See examples/data/ourdb_server.vsh
|
||||||
|
import freeflowuniverse.herolib.data.ourdb
|
||||||
|
import os
|
||||||
|
|
||||||
|
mut client := ourdb.new_client(
|
||||||
|
port: 3000
|
||||||
|
host: 'localhost'
|
||||||
|
)!
|
||||||
|
|
||||||
|
set := client.set('hello')!
|
||||||
|
get := client.get(set.id)!
|
||||||
|
|
||||||
|
assert set.id == get.id
|
||||||
|
|
||||||
|
println('Set result: ${set}')
|
||||||
|
println('Get result: ${get}')
|
||||||
|
|
||||||
|
// test delete functionality
|
||||||
|
|
||||||
|
client.delete(set.id)!
|
||||||
@@ -4,7 +4,7 @@ import freeflowuniverse.herolib.data.ourdb
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
mut server := ourdb.new_server(
|
mut server := ourdb.new_server(
|
||||||
port: 9000
|
port: 3000
|
||||||
allowed_hosts: ['localhost']
|
allowed_hosts: ['localhost']
|
||||||
allowed_operations: ['set', 'get', 'delete']
|
allowed_operations: ['set', 'get', 'delete']
|
||||||
secret_key: 'secret'
|
secret_key: 'secret'
|
||||||
|
|||||||
35
lib/data/ourdb/CLIENT.md
Normal file
35
lib/data/ourdb/CLIENT.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# OurDB Client
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
This client is created to interact with an OurDB server.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
Before running the client script, ensure that the OurDB server is up and running. You can start the server by following the instructions in the [OurDB Server README](./SERVER.md).
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Ensure you have the V programming language installed. You can download it from [vlang.io](https://vlang.io/).
|
||||||
|
|
||||||
|
## Running the Client
|
||||||
|
|
||||||
|
Once the OurDB server is running, execute the client script:
|
||||||
|
```sh
|
||||||
|
examples/data/ourdb_client.vsh
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can run it using V:
|
||||||
|
```sh
|
||||||
|
v -enable-globals run ourdb_client.vsh
|
||||||
|
```
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
1. Connects to the OurDB server on `localhost:3000`.
|
||||||
|
2. Sets a record with the value `hello`.
|
||||||
|
3. Retrieves the record by ID and verifies the stored value.
|
||||||
|
4. Deletes the record.
|
||||||
|
|
||||||
|
## Example Output
|
||||||
|
```
|
||||||
|
Set result: { id: 1, value: 'hello' }
|
||||||
|
Get result: { id: 1, value: 'hello' }
|
||||||
|
```
|
||||||
90
lib/data/ourdb/client.v
Normal file
90
lib/data/ourdb/client.v
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
module ourdb
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.ui.console
|
||||||
|
import freeflowuniverse.herolib.core.httpconnection
|
||||||
|
import json
|
||||||
|
|
||||||
|
pub struct OurDBClient {
|
||||||
|
pub mut:
|
||||||
|
conn httpconnection.HTTPConnection
|
||||||
|
port int // Server port, default is 3000
|
||||||
|
host string
|
||||||
|
}
|
||||||
|
|
||||||
|
@[params]
|
||||||
|
pub struct OurDBClientArgs {
|
||||||
|
pub mut:
|
||||||
|
port int = 3000 // Server port, default is 3000
|
||||||
|
host string = 'localhost' // Server host
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Response[T] {
|
||||||
|
message string // Success message
|
||||||
|
data T // Response data
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_client(args OurDBClientArgs) !OurDBClient {
|
||||||
|
mut client := OurDBClient{
|
||||||
|
port: args.port
|
||||||
|
host: args.host
|
||||||
|
}
|
||||||
|
client.conn = client.connection()!
|
||||||
|
console.print_green('Client started')
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut client OurDBClient) connection() !&httpconnection.HTTPConnection {
|
||||||
|
mut http := httpconnection.new(
|
||||||
|
name: 'ourdb_client'
|
||||||
|
url: 'http://${client.host}:${client.port}'
|
||||||
|
cache: true
|
||||||
|
retry: 3
|
||||||
|
)!
|
||||||
|
|
||||||
|
client.conn = http
|
||||||
|
return http
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets a value in the database
|
||||||
|
pub fn (mut client OurDBClient) set(data string) !KeyValueData {
|
||||||
|
mut request_body := json.encode({
|
||||||
|
'value': data
|
||||||
|
})
|
||||||
|
|
||||||
|
req := httpconnection.Request{
|
||||||
|
prefix: 'set'
|
||||||
|
method: .post
|
||||||
|
data: request_body
|
||||||
|
}
|
||||||
|
|
||||||
|
mut http := client.connection()!
|
||||||
|
response := http.post_json_str(req)!
|
||||||
|
|
||||||
|
mut decoded_response := json.decode(Response[KeyValueData], response)!
|
||||||
|
return decoded_response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets a value in the database based on it's ID
|
||||||
|
pub fn (mut client OurDBClient) get(id u32) !KeyValueData {
|
||||||
|
req := httpconnection.Request{
|
||||||
|
prefix: 'get/${id}'
|
||||||
|
method: .get
|
||||||
|
}
|
||||||
|
|
||||||
|
mut http := client.connection()!
|
||||||
|
response := http.get_json(req)!
|
||||||
|
|
||||||
|
mut decoded_response := json.decode(Response[KeyValueData], response)!
|
||||||
|
return decoded_response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deletes a value in the database based on it's ID
|
||||||
|
pub fn (mut client OurDBClient) delete(id u32) ! {
|
||||||
|
req := httpconnection.Request{
|
||||||
|
prefix: 'delete/${id}'
|
||||||
|
method: .delete
|
||||||
|
}
|
||||||
|
|
||||||
|
mut http := client.connection()!
|
||||||
|
http.delete(req) or { return error('Failed to delete key due to: ${err}') }
|
||||||
|
}
|
||||||
@@ -136,8 +136,8 @@ fn (server OurDBServer) success[T](args SuccessResponse[T]) SuccessResponse[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Request body structure for the `/set` endpoint
|
// Request body structure for the `/set` endpoint
|
||||||
struct SetRequestBody {
|
pub struct KeyValueData {
|
||||||
mut:
|
pub mut:
|
||||||
id u32 // Record ID
|
id u32 // Record ID
|
||||||
value string // Value to store
|
value string // Value to store
|
||||||
}
|
}
|
||||||
@@ -146,7 +146,7 @@ mut:
|
|||||||
@['/set'; post]
|
@['/set'; post]
|
||||||
pub fn (mut server OurDBServer) set(mut ctx ServerContext) veb.Result {
|
pub fn (mut server OurDBServer) set(mut ctx ServerContext) veb.Result {
|
||||||
request_body := ctx.req.data.str()
|
request_body := ctx.req.data.str()
|
||||||
mut decoded_body := json.decode(SetRequestBody, request_body) or {
|
mut decoded_body := json.decode(KeyValueData, request_body) or {
|
||||||
ctx.res.set_status(.bad_request)
|
ctx.res.set_status(.bad_request)
|
||||||
return ctx.json[ErrorResponse](server.error(
|
return ctx.json[ErrorResponse](server.error(
|
||||||
error: 'bad_request'
|
error: 'bad_request'
|
||||||
@@ -197,7 +197,7 @@ pub fn (mut server OurDBServer) get(mut ctx ServerContext, id string) veb.Result
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
data := SetRequestBody{
|
data := KeyValueData{
|
||||||
id: id_
|
id: id_
|
||||||
value: record.bytestr()
|
value: record.bytestr()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user