one_punch.rs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. use crate::nockapp::driver::*;
  2. use crate::nockapp::wire::Wire;
  3. use crate::nockapp::NockAppError;
  4. use crate::noun::slab::NounSlab;
  5. use either::Either::{self, Left, Right};
  6. use sword::noun::D;
  7. use sword_macros::tas;
  8. use tracing::{debug, error, info};
  9. pub enum OnePunchWire {
  10. Poke,
  11. }
  12. impl Wire for OnePunchWire {
  13. const VERSION: u64 = 1;
  14. const SOURCE: &'static str = "one-punch";
  15. }
  16. pub fn one_punch_man(data: NounSlab, op: Operation) -> IODriverFn {
  17. make_driver(|handle| async move {
  18. let wire = OnePunchWire::Poke.to_wire();
  19. let result = match op {
  20. Operation::Poke => Left(handle.poke(wire, data).await?),
  21. Operation::Peek => {
  22. debug!("poke_once_driver: peeking with {:?}", data);
  23. Right(handle.peek(data).await?)
  24. }
  25. };
  26. tokio::select! {
  27. res = handle_result(result, &op) => res,
  28. eff = handle.next_effect() => {
  29. handle_effect(eff, &handle).await
  30. },
  31. _ = tokio::time::sleep(tokio::time::Duration::from_secs(600)) => {
  32. //TODO what is a good timeout for tests?
  33. info!("poke_once_driver: no effect received after 10 minutes");
  34. Err(NockAppError::Timeout)
  35. }
  36. }
  37. })
  38. }
  39. /// Handles the result of a poke or peek operation.
  40. ///
  41. /// Poke:
  42. /// - Ack: The poke operation was successful.
  43. /// - Nack: The poke operation failed.
  44. ///
  45. /// Peek:
  46. /// - Some(NounSlab): The peek operation was successful and returned a NounSlab.
  47. /// - None: The peek operation failed or returned no result.
  48. ///
  49. /// # Arguments
  50. ///
  51. /// * `result` - The result of the operation.
  52. /// * `op` - The operation type (Poke or Peek).
  53. ///
  54. /// # Returns
  55. ///
  56. /// A Result indicating success or failure of the operation.
  57. async fn handle_result(
  58. result: Either<PokeResult, Option<NounSlab>>,
  59. op: &Operation,
  60. ) -> Result<(), NockAppError> {
  61. match op {
  62. Operation::Poke => match result {
  63. Left(PokeResult::Ack) => {
  64. info!("Poke successful");
  65. Ok(())
  66. }
  67. Left(PokeResult::Nack) => {
  68. error!("Poke nacked");
  69. Err(NockAppError::PokeFailed)
  70. }
  71. Right(_) => {
  72. error!("Unexpected result for poke operation");
  73. Err(NockAppError::UnexpectedResult)
  74. }
  75. },
  76. Operation::Peek => match result {
  77. Left(_) => {
  78. error!("Unexpected result for peek operation");
  79. Err(NockAppError::UnexpectedResult)
  80. }
  81. Right(Some(peek_result)) => {
  82. info!("Peek result: {:?}", peek_result);
  83. Ok(())
  84. }
  85. Right(_) => {
  86. error!("Peek returned no result");
  87. Err(NockAppError::PeekFailed)
  88. }
  89. },
  90. }
  91. }
  92. /// Handles effects from the kernel.
  93. ///
  94. /// # Arguments
  95. ///
  96. /// * `eff` - The effect produced by the kernel.
  97. /// * `_handle` - The NockAppHandle (unused in this implementation).
  98. ///
  99. /// # Returns
  100. ///
  101. /// A Result indicating success or failure of handling the effect.
  102. async fn handle_effect(
  103. eff: Result<NounSlab, NockAppError>,
  104. _handle: &NockAppHandle,
  105. ) -> Result<(), NockAppError> {
  106. let eff = eff?;
  107. debug!("poke_once_driver: effect received: {:?}", eff);
  108. // Split out root bindings so they don't get dropped early
  109. let root = unsafe { eff.root() };
  110. debug!("poke_once_driver: root: {:?}", root);
  111. let effect_cell = root.as_cell().unwrap_or_else(|err| {
  112. panic!(
  113. "Panicked with {err:?} at {}:{} (git sha: {:?})",
  114. file!(),
  115. line!(),
  116. option_env!("GIT_SHA")
  117. )
  118. });
  119. if unsafe { effect_cell.head().raw_equals(&D(tas!(b"npc"))) } {
  120. let npc_effect = effect_cell.tail();
  121. if let Ok(npc_effect_cell) = npc_effect.as_cell() {
  122. match npc_effect_cell
  123. .head()
  124. .as_atom()
  125. .unwrap_or_else(|err| {
  126. panic!(
  127. "Panicked with {err:?} at {}:{} (git sha: {:?})",
  128. file!(),
  129. line!(),
  130. option_env!("GIT_SHA")
  131. )
  132. })
  133. .as_u64()
  134. .expect("Failed to convert to u64")
  135. {
  136. tas!(b"gossip") => {
  137. // Ignore gossip data
  138. info!("Ignoring gossip data");
  139. }
  140. tas!(b"request") => {
  141. info!("Processing request effect");
  142. let request_data = npc_effect_cell.tail();
  143. info!("Request data: {:?}", request_data);
  144. // handle.poke(create_response(request_data)).await?;
  145. }
  146. _ => info!("Received unknown npc effect"),
  147. }
  148. }
  149. }
  150. Ok(())
  151. }