use heromodels::db::postgres::{Config, Postgres}; use heromodels::db::{Collection, Db}; use heromodels::models::grid4::node::node_index::{country, nodegroupid, pubkey}; use heromodels::models::grid4::node::{ComputeSlice, DeviceInfo, Node}; use heromodels_core::Model; // Requires local Postgres (user=postgres password=test123 host=localhost port=5432) // Run with: cargo test -p heromodels --test grid4_postgres -- --ignored #[test] #[ignore] fn grid4_node_postgres_roundtrip_like_example() { let db = Postgres::new( Config::new() .user(Some("postgres".into())) .password(Some("test123".into())) .host(Some("localhost".into())) .port(Some(5432)), ) .expect("can connect to Postgres"); let nodes = db.collection::().expect("open node collection"); // Clean existing if let Ok(existing) = nodes.get_all() { for n in existing { let _ = nodes.delete_by_id(n.get_id()); } } // Build and store multiple nodes via builder and then persist via collection.set(), like examples let cs1 = ComputeSlice::new() .nodeid(10) .slice_id(1) .mem_gb(32.0) .storage_gb(512.0) .passmark(5000) .vcores(16) .gpus(1) .price_cc(0.25); let cs2 = ComputeSlice::new() .nodeid(10) .slice_id(2) .mem_gb(64.0) .storage_gb(2048.0) .passmark(7000) .vcores(24) .gpus(2) .price_cc(0.50); let cs3 = ComputeSlice::new() .nodeid(11) .slice_id(1) .mem_gb(16.0) .storage_gb(256.0) .passmark(3000) .vcores(8) .gpus(0) .price_cc(0.10); let dev = DeviceInfo { vendor: "ACME".into(), ..Default::default() }; let n1 = Node::new() .nodegroupid(99) .uptime(97) .add_compute_slice(cs1) .devices(dev.clone()) .country("BE") .pubkey("PG_NODE_1") .build(); let n2 = Node::new() .nodegroupid(99) .uptime(96) .add_compute_slice(cs2) .devices(dev.clone()) .country("NL") .pubkey("PG_NODE_2") .build(); let n3 = Node::new() .nodegroupid(7) .uptime(95) .add_compute_slice(cs3) .devices(dev) .country("BE") .pubkey("PG_NODE_3") .build(); let (id1, s1) = nodes.set(&n1).expect("store n1"); let (id2, s2) = nodes.set(&n2).expect("store n2"); let (id3, s3) = nodes.set(&n3).expect("store n3"); assert!(id1 > 0 && id2 > 0 && id3 > 0); // Query by top-level indexes similar to the example style let be_nodes = nodes.get::("BE").expect("by country"); assert_eq!(be_nodes.len(), 2); let grp_99 = nodes.get::(&99).expect("by group"); assert_eq!(grp_99.len(), 2); let by_key = nodes.get::("PG_NODE_2").expect("by pubkey"); assert_eq!(by_key.len(), 1); assert_eq!(by_key[0].get_id(), id2); // Update: change country of n1 let updated = s1.clone().country("DE"); let (_, back) = nodes.set(&updated).expect("update n1"); assert_eq!(back.country, "DE"); // Cardinality after update let de_nodes = nodes.get::("DE").expect("by country DE"); assert_eq!(de_nodes.len(), 1); // Delete by id and by index nodes.delete_by_id(id2).expect("delete n2 by id"); assert!(nodes.get_by_id(id2).unwrap().is_none()); nodes.delete::("PG_NODE_3").expect("delete n3 by pubkey"); assert!(nodes.get_by_id(id3).unwrap().is_none()); // Remaining should be updated n1 only; verify via targeted queries let de_nodes = nodes.get::("DE").expect("country DE after deletes"); assert_eq!(de_nodes.len(), 1); assert_eq!(de_nodes[0].get_id(), id1); let by_key = nodes.get::("PG_NODE_1").expect("by pubkey PG_NODE_1"); assert_eq!(by_key.len(), 1); assert_eq!(by_key[0].get_id(), id1); }