Deployment and lifecycle management for Nix
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

client: enable channel registration of tree and id retrieval

+76 -63
+1 -1
client/src/main.rs
··· 173 173 // cli overrides config 174 174 let config = config.name(cli.name).seed_type(cli.seed_type).url(cli.url); 175 175 176 - let tree = Tree::new(&config).await?; 176 + let mut tree = Tree::new(&config).await?; 177 177 let seed = &tree.seed.as_ref(); 178 178 179 179 match &cli.action {
+11 -6
client/src/sower.rs
··· 1 1 use crate::*; 2 + use serde::Serialize; 2 3 3 4 pub mod daemon; 4 5 ··· 70 71 } 71 72 } 72 73 73 - #[derive(Clone, Copy, Debug, Deserialize, Display, PartialEq, ValueEnum, VariantNames)] 74 + #[derive( 75 + Clone, Copy, Debug, Deserialize, Display, PartialEq, Serialize, ValueEnum, VariantNames, 76 + )] 74 77 #[serde(rename_all = "kebab-case")] 75 78 #[strum(serialize_all = "kebab-case")] 76 79 pub enum SeedType { ··· 90 93 None, 91 94 } 92 95 93 - #[derive(Clone, Debug)] 96 + #[derive(Clone, Debug, Deserialize)] 94 97 pub struct Sower { 95 98 pub url: String, 96 99 pub api_url: String, ··· 114 117 let client = reqwest::Client::new(); 115 118 116 119 match client 117 - .get(format!("{}/seeds/latest", &self.url)) 120 + .get(format!("{}/seeds/latest", &self.api_url)) 118 121 .query(&[("name", name), ("type", seed_type.to_string())]) 119 122 .send() 120 123 .await ··· 131 134 } 132 135 } 133 136 134 - #[derive(Debug)] 137 + #[derive(Debug, Deserialize)] 135 138 pub struct Tree { 136 139 pub name: String, 137 140 pub seed: Option<Seed>, 138 141 pub seed_type: SeedType, 139 - pub sower: Sower, 142 + pub sower: Option<Sower>, 143 + pub id: Option<String>, 140 144 } 141 145 142 146 impl Tree { ··· 158 162 Ok(Tree { 159 163 name: name.clone(), 160 164 seed_type, 161 - sower: sower.clone(), 165 + sower: Some(sower.clone()), 162 166 seed: sower.find_seed(name, seed_type).await, 167 + id: None, 163 168 }) 164 169 } 165 170
+41 -54
client/src/sower/daemon.rs
··· 5 5 use phoenix_channels_client::url::Url; 6 6 use serde_json::json; 7 7 8 - use phoenix_channels_client::{Event, EventPayload, EventsError, Payload, Socket, Topic}; 8 + use phoenix_channels_client::{Event, EventPayload, EventsError, Payload, Socket, Topic, JSON}; 9 9 10 10 impl Tree { 11 - pub async fn daemon(&self) -> Result<(), std::io::Error> { 12 - dbg!(&self.sower.channels_url); 13 - 14 - // URL with params for authentication 15 - let url = Url::parse(&self.sower.channels_url).unwrap(); 16 - 17 - // Create a socket 11 + pub async fn daemon(&mut self) -> Result<(), std::io::Error> { 12 + let url = Url::parse(&self.sower.clone().unwrap().channels_url).unwrap(); 18 13 let socket = Socket::spawn(url, None).unwrap(); 19 - 20 - // Connect the socket 21 14 socket.connect(Duration::from_secs(10)).await.unwrap(); 22 15 23 - // Create a channel with no params 24 16 let topic = Topic::from_string("tree:all".to_string()); 25 17 let channel = socket.channel(topic.clone(), None).await.unwrap(); 26 - //let some_event_channel = channel.clone(); 27 - 28 - // Events are received as a broadcast with the name of the event and payload associated with the event 29 18 let events = channel.events(); 30 - tokio::spawn(async move { 31 - loop { 32 - match events.event().await { 33 - Ok(EventPayload { event, payload }) => match event { 34 - Event::User { 35 - user: user_event_name, 36 - } => println!( 37 - "channel {} event {} sent with payload {:#?}", 38 - topic, user_event_name, payload 39 - ), 40 - Event::Phoenix { phoenix } => println!("channel {} {}", topic, phoenix), 41 - }, 42 - Err(events_error) => match events_error { 43 - EventsError::NoMoreEvents => break, 44 - EventsError::MissedEvents { missed_event_count } => { 45 - eprintln!("{} events missed on channel {}", missed_event_count, topic); 46 - } 47 - }, 48 - } 49 - } 50 - }); 51 - // Join the channel with a 15 second timeout 52 19 channel.join(Duration::from_secs(15)).await.unwrap(); 53 20 54 - // Send a message, waiting for a reply until timeout 55 - let reply_payload = channel 21 + let Payload::JSONPayload { json } = channel 56 22 .call( 57 - Event::from_string("reply_ok_tuple".to_string()), 58 - Payload::json_from_serialized(json!({ "name": "foo", "message": "hi"}).to_string()) 59 - .unwrap(), 23 + Event::from_string("register".to_string()), 24 + Payload::json_from_serialized( 25 + json!({ "name": &self.name, "type": &self.seed_type}).to_string(), 26 + ) 27 + .unwrap(), 60 28 Duration::from_secs(5), 61 29 ) 62 30 .await 63 - .unwrap(); 31 + .unwrap() 32 + else { 33 + panic!("unable to register") 34 + }; 64 35 65 - dbg!(reply_payload); 36 + self.id = if let JSON::Str { string, .. } = &json { 37 + Some(string.to_string()) 38 + } else { 39 + panic!("unable to parse registration response") 40 + }; 66 41 67 - // Send a message, not waiting for a reply 68 - channel 69 - .cast( 70 - Event::from_string("noreply".to_string()), 71 - Payload::json_from_serialized( 72 - json!({ "name": "foo", "message": "jeez"}).to_string(), 73 - ) 74 - .unwrap(), 75 - ) 76 - .await 77 - .unwrap(); 42 + tokio::select! { 43 + _ = async { 44 + loop { 45 + match events.event().await { 46 + Ok(EventPayload { event, payload }) => match event { 47 + Event::User { 48 + user: user_event_name, 49 + } => println!( 50 + "channel {} event {} sent with payload {:#?}", 51 + topic, user_event_name, payload 52 + ), 53 + Event::Phoenix { phoenix } => println!("channel {} {}", topic, phoenix), 54 + }, 55 + Err(events_error) => match events_error { 56 + EventsError::NoMoreEvents => break, 57 + EventsError::MissedEvents { missed_event_count } => { 58 + eprintln!("{} events missed on channel {}", missed_event_count, topic); 59 + } 60 + }, 61 + } 62 + } 63 + } => {} 64 + } 78 65 79 66 // Leave the channel 80 67 channel.leave().await.unwrap();
+12
lib/sower/tree.ex
··· 4 4 domain: Sower, 5 5 extensions: [AshJsonApi.Resource] 6 6 7 + @derive {Jason.Encoder, only: [:id, :name, :type]} 8 + 7 9 @types [:nixos, :"home-manager", :"nix-darwin"] 8 10 9 11 actions do ··· 22 24 get? true 23 25 24 26 filter expr(id == ^arg(:id)) 27 + end 28 + 29 + read :find do 30 + argument :name, :string, allow_nil?: false 31 + argument :type, :string, allow_nil?: false 32 + 33 + get? true 34 + 35 + filter expr(name == ^arg(:name) && type == ^arg(:type)) 25 36 end 26 37 27 38 update :set_seed do ··· 54 65 55 66 code_interface do 56 67 define :by_id, args: [:id] 68 + define :find, args: [:name, :type] 57 69 define :set_seed, args: [:seed_id] 58 70 define :read_all, action: :read 59 71 define :register, args: [:name, :type]
+9 -2
lib/sower_web/tree_channel.ex
··· 9 9 {:error, %{reason: "unauthorized"}} 10 10 end 11 11 12 - def handle_in("reply_ok_tuple", body, socket) do 13 - {:reply, {:ok, "success"}, socket} 12 + def handle_in("register", %{"name" => name, "type" => type}, socket) do 13 + id = 14 + with {:ok, tree} <- Sower.Tree.register(name, type) do 15 + tree.id 16 + else 17 + {:error, _} -> Sower.Tree.find!(name, type) |> Map.get(:id) 18 + end 19 + 20 + {:reply, {:ok, id}, socket} 14 21 end 15 22 end
+2
rustfmt.toml
··· 1 + edition = "2021" 2 +