feat: improve build and serialization logic
- Update v fmt exit code handling - Support dynamic organization for symlinks - Add f32 and list f64 serialization/deserialization - Improve JSON decoding for bid requirements/pricing - Add basic tests for Bid and Node creation
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -56,4 +56,5 @@ MCP_HTTP_REST_IMPLEMENTATION_PLAN.md
|
|||||||
.continue
|
.continue
|
||||||
tmux_logger
|
tmux_logger
|
||||||
release
|
release
|
||||||
install_herolib
|
install_herolib
|
||||||
|
doc
|
||||||
15
doc.vsh
15
doc.vsh
@@ -6,15 +6,22 @@ abs_dir_of_script := dir(@FILE)
|
|||||||
|
|
||||||
// Format code
|
// Format code
|
||||||
println('Formatting code...')
|
println('Formatting code...')
|
||||||
if os.system('v fmt -w ${abs_dir_of_script}/examples') != 0 {
|
// v fmt returns:
|
||||||
eprintln('Warning: Failed to format examples')
|
// - 0: all files already formatted (no changes)
|
||||||
|
// - 5: files were formatted (changes made) - this is SUCCESS
|
||||||
|
// - other: actual errors (syntax errors, file access issues, etc.)
|
||||||
|
fmt_examples_result := os.system('v fmt -w ${abs_dir_of_script}/examples')
|
||||||
|
if fmt_examples_result != 0 && fmt_examples_result != 5 {
|
||||||
|
eprintln('Error: Failed to format examples (exit code: ${fmt_examples_result})')
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.system('v fmt -w ${abs_dir_of_script}/lib') != 0 {
|
fmt_lib_result := os.system('v fmt -w ${abs_dir_of_script}/lib')
|
||||||
eprintln('Warning: Failed to format herolib')
|
if fmt_lib_result != 0 && fmt_lib_result != 5 {
|
||||||
|
eprintln('Error: Failed to format herolib (exit code: ${fmt_lib_result})')
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
println('✓ Code formatting completed')
|
||||||
|
|
||||||
// Clean existing docs
|
// Clean existing docs
|
||||||
println('Cleaning existing documentation...')
|
println('Cleaning existing documentation...')
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ abs_dir_of_script := dir(@FILE)
|
|||||||
println('Script directory: ${abs_dir_of_script}')
|
println('Script directory: ${abs_dir_of_script}')
|
||||||
|
|
||||||
// Determine the organization name from the current path
|
// Determine the organization name from the current path
|
||||||
// This makes the script work with any organization (incubaid, freeflowuniverse, etc.)
|
// This makes the script work with any organization (incubaid, etc.)
|
||||||
path_parts := abs_dir_of_script.split('/')
|
path_parts := abs_dir_of_script.split('/')
|
||||||
mut org_name := 'incubaid' // default fallback
|
mut org_name := 'incubaid' // default fallback
|
||||||
for i, part in path_parts {
|
for i, part in path_parts {
|
||||||
@@ -60,32 +60,35 @@ for i, part in path_parts {
|
|||||||
println('Detected organization: ${org_name}')
|
println('Detected organization: ${org_name}')
|
||||||
println('Will create symlink: ${os.home_dir()}/.vmodules/${org_name}/herolib -> ${abs_dir_of_script}/lib')
|
println('Will create symlink: ${os.home_dir()}/.vmodules/${org_name}/herolib -> ${abs_dir_of_script}/lib')
|
||||||
|
|
||||||
// Reset symlinks for both possible organizations (cleanup)
|
// Reset symlinks (cleanup)
|
||||||
println('Resetting all symlinks...')
|
println('Resetting all symlinks...')
|
||||||
os.rm('${os.home_dir()}/.vmodules/freeflowuniverse/herolib') or {}
|
|
||||||
os.rm('${os.home_dir()}/.vmodules/incubaid/herolib') or {}
|
os.rm('${os.home_dir()}/.vmodules/incubaid/herolib') or {}
|
||||||
os.rm('${os.home_dir()}/.vmodules/${org_name}/herolib') or {}
|
os.rm('${os.home_dir()}/.vmodules/${org_name}/herolib') or {}
|
||||||
|
|
||||||
// Create necessary directories
|
// Create necessary directories
|
||||||
os.mkdir_all('${os.home_dir()}/.vmodules/freeflowuniverse') or {
|
os.mkdir_all('${os.home_dir()}/.vmodules/${org_name}') or {
|
||||||
panic('Failed to create directory ~/.vmodules/freeflowuniverse: ${err}')
|
panic('Failed to create directory ~/.vmodules/${org_name}: ${err}')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new symlinks
|
// Create new symlinks
|
||||||
os.symlink('${abs_dir_of_script}/lib', '${os.home_dir()}/.vmodules/freeflowuniverse/herolib') or {
|
symlink_target := '${abs_dir_of_script}/lib'
|
||||||
panic('Failed to create herolib symlink: ${err}')
|
symlink_path := '${os.home_dir()}/.vmodules/${org_name}/herolib'
|
||||||
}
|
|
||||||
|
os.symlink(symlink_target, symlink_path) or { panic('Failed to create herolib symlink: ${err}') }
|
||||||
|
|
||||||
// Verify the symlink was created
|
// Verify the symlink was created
|
||||||
symlink_path := '${os.home_dir()}/.vmodules/${org_name}/herolib'
|
// Note: os.exists() may return false for broken symlinks, so we check if it's a link first
|
||||||
if os.exists(symlink_path) {
|
if os.is_link(symlink_path) {
|
||||||
println('✓ Symlink created successfully: ${symlink_path}')
|
println('✓ Symlink created successfully: ${symlink_path}')
|
||||||
// Verify it points to the right location
|
println('✓ Points to: ${symlink_target}')
|
||||||
if os.is_link(symlink_path) {
|
// Verify the target exists
|
||||||
println('✓ Confirmed: ${symlink_path} is a symbolic link')
|
if os.exists(symlink_target) {
|
||||||
|
println('✓ Target directory exists and is accessible')
|
||||||
|
} else {
|
||||||
|
eprintln('⚠ Warning: Symlink target does not exist: ${symlink_target}')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic('Failed to verify herolib symlink at ${symlink_path}')
|
panic('Failed to create herolib symlink at ${symlink_path}')
|
||||||
}
|
}
|
||||||
|
|
||||||
println('Herolib installation completed successfully!')
|
println('Herolib installation completed successfully!')
|
||||||
|
|||||||
@@ -136,6 +136,14 @@ pub fn (mut d Decoder) get_f64() !f64 {
|
|||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut d Decoder) get_f32() !f32 {
|
||||||
|
// Get the u32 bits first and then convert back to f32
|
||||||
|
bits := d.get_u32()!
|
||||||
|
// Use unsafe to convert bits to f32
|
||||||
|
f := unsafe { *(&f32(&bits)) }
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut d Decoder) get_time() !time.Time {
|
pub fn (mut d Decoder) get_time() !time.Time {
|
||||||
secs_ := d.get_u32()!
|
secs_ := d.get_u32()!
|
||||||
secs := i64(secs_)
|
secs := i64(secs_)
|
||||||
@@ -229,6 +237,15 @@ pub fn (mut d Decoder) get_list_u64() ![]u64 {
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut d Decoder) get_list_f64() ![]f64 {
|
||||||
|
n := d.get_u16()!
|
||||||
|
mut v := []f64{len: int(n)}
|
||||||
|
for i in 0 .. n {
|
||||||
|
v[i] = d.get_f64()!
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut d Decoder) get_map_string() !map[string]string {
|
pub fn (mut d Decoder) get_map_string() !map[string]string {
|
||||||
n := d.get_u16()!
|
n := d.get_u16()!
|
||||||
mut v := map[string]string{}
|
mut v := map[string]string{}
|
||||||
|
|||||||
@@ -115,6 +115,13 @@ pub fn (mut b Encoder) add_f64(data f64) {
|
|||||||
b.add_u64(bits)
|
b.add_u64(bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// adds a float32 value
|
||||||
|
pub fn (mut b Encoder) add_f32(data f32) {
|
||||||
|
// Convert f32 to bits first, then store as u32
|
||||||
|
bits := unsafe { *(&u32(&data)) }
|
||||||
|
b.add_u32(bits)
|
||||||
|
}
|
||||||
|
|
||||||
// adds gid as a string
|
// adds gid as a string
|
||||||
pub fn (mut b Encoder) add_gid(data gid.GID) {
|
pub fn (mut b Encoder) add_gid(data gid.GID) {
|
||||||
b.add_string(data.str())
|
b.add_string(data.str())
|
||||||
@@ -185,6 +192,16 @@ pub fn (mut b Encoder) add_list_u64(data []u64) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut b Encoder) add_list_f64(data []f64) {
|
||||||
|
if data.len > 64 * kb {
|
||||||
|
panic('list cannot have more than 64kb items.')
|
||||||
|
}
|
||||||
|
b.add_u16(u16(data.len)) // how many items in list
|
||||||
|
for item in data {
|
||||||
|
b.add_f64(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// when complicated hash e.g. map of other object need to serialize each sub object
|
// when complicated hash e.g. map of other object need to serialize each sub object
|
||||||
pub fn (mut b Encoder) add_map_string(data map[string]string) {
|
pub fn (mut b Encoder) add_map_string(data map[string]string) {
|
||||||
if data.len > 64 * kb {
|
if data.len > 64 * kb {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ module models_tfgrid
|
|||||||
import incubaid.herolib.data.encoder
|
import incubaid.herolib.data.encoder
|
||||||
import incubaid.herolib.data.ourtime
|
import incubaid.herolib.data.ourtime
|
||||||
import incubaid.herolib.hero.db
|
import incubaid.herolib.hero.db
|
||||||
import incubaid.herolib.data.json
|
import json
|
||||||
|
|
||||||
// Bid - ROOT OBJECT
|
// Bid - ROOT OBJECT
|
||||||
@[heap]
|
@[heap]
|
||||||
@@ -106,8 +106,10 @@ pub fn (self Bid) dump(mut e encoder.Encoder) ! {
|
|||||||
|
|
||||||
fn (mut self DBBid) load(mut o Bid, mut e encoder.Decoder) ! {
|
fn (mut self DBBid) load(mut o Bid, mut e encoder.Decoder) ! {
|
||||||
o.customer_id = e.get_u32()!
|
o.customer_id = e.get_u32()!
|
||||||
o.requirements = json.decode[map[string]string](e.get_string()!)!
|
requirements_str := e.get_string()!
|
||||||
o.pricing = json.decode[map[string]string](e.get_string()!)!
|
o.requirements = json.decode(map[string]string, requirements_str)!
|
||||||
|
pricing_str := e.get_string()!
|
||||||
|
o.pricing = json.decode(map[string]string, pricing_str)!
|
||||||
o.status = unsafe { BidStatus(e.get_int()!) }
|
o.status = unsafe { BidStatus(e.get_int()!) }
|
||||||
o.obligation = e.get_bool()!
|
o.obligation = e.get_bool()!
|
||||||
o.start_date = e.get_u32()!
|
o.start_date = e.get_u32()!
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
module models_tfgrid
|
|
||||||
|
|
||||||
// Re-export all the root objects and their supporting structures
|
|
||||||
pub use node
|
|
||||||
pub use nodegroup
|
|
||||||
pub use bid
|
|
||||||
pub use contract
|
|
||||||
pub use reputation
|
|
||||||
39
lib/threefold/models_tfgrid/models_tfgrid_test.v
Normal file
39
lib/threefold/models_tfgrid/models_tfgrid_test.v
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
module models_tfgrid
|
||||||
|
|
||||||
|
fn test_bid_creation() {
|
||||||
|
// Just a simple test to verify the module compiles
|
||||||
|
bid := Bid{
|
||||||
|
customer_id: 123
|
||||||
|
requirements: {
|
||||||
|
'compute_nodes': '10'
|
||||||
|
}
|
||||||
|
pricing: {
|
||||||
|
'compute_nodes': '10.2'
|
||||||
|
}
|
||||||
|
status: .pending
|
||||||
|
obligation: true
|
||||||
|
start_date: 1234567890
|
||||||
|
end_date: 1234567890
|
||||||
|
signature_user: 'test_signature'
|
||||||
|
billing_period: .monthly
|
||||||
|
}
|
||||||
|
|
||||||
|
assert bid.customer_id == 123
|
||||||
|
assert bid.status == .pending
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_node_creation() {
|
||||||
|
// Just a simple test to verify the module compiles
|
||||||
|
node := Node{
|
||||||
|
nodegroupid: 456
|
||||||
|
country: 'US'
|
||||||
|
uptime: 99
|
||||||
|
pubkey: 'test_pubkey'
|
||||||
|
signature_node: 'test_sig_node'
|
||||||
|
signature_farmer: 'test_sig_farmer'
|
||||||
|
}
|
||||||
|
|
||||||
|
assert node.nodegroupid == 456
|
||||||
|
assert node.country == 'US'
|
||||||
|
assert node.uptime == 99
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user