Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_bot/src/bot.rs

3.0 KiB, 29 runs

created by r1870400018:38, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1use crate::{
2 msg::BotMsg,
3};
4
5use oxedyne_fe2o3_core::{
6 prelude::*,
7 channels::Simplex,
8};
9use oxedyne_fe2o3_jdat::id::NumIdDat;
10
11use std::{
12 sync::{
13 Arc,
14 Mutex,
15 },
16};
17
18/// A labelled intention to exit a bot listen loop.
19#[derive(Clone, Debug, Eq, PartialEq)]
20pub struct LoopBreak(pub bool);
21
22impl LoopBreak {
23 pub fn must_end(&self) -> bool { self.0 }
24}
25
26pub trait Bot<
27 const BIDL: usize,
28 BID: NumIdDat<BIDL>,
29 M: BotMsg<ErrTag>,
30> {
31
32 // Required.
33 // Getters.
34 fn id(&self) -> BID;
35 fn errc(&self) -> &Arc<Mutex<usize>>;
36 fn chan_in(&self) -> &Simplex<M>;
37 fn label(&self) -> String;
38 fn err_count_warning(&self) -> usize;
39 fn log_stream_id(&self) -> String;
40 // Setters.
41 fn set_chan_in(&mut self, chan_in: Simplex<M>);
42 // Procedures.
43 fn init(&mut self) -> Outcome<()> { Ok(()) }
44 fn go(&mut self) {}
45 fn listen(&mut self) -> LoopBreak { LoopBreak(true) }
46
47 // Provided.
48
49 fn now_listening(&self) {
50 info!("{}: Now listening for internal messages...", self.label());
51 }
52
53 fn err_cannot_send(&self, e: Error<ErrTag>) {
54 error!(err!(e, "{:?}: could not send to a channnel.", self.id(); Channel, Write));
55 self.inc_err();
56 }
57
58 fn err_cannot_receive(&self, e: Error<ErrTag>) {
59 error!(err!(e, "{:?}: could not receive from channnel.", self.id(); Channel, Read));
60 self.inc_err();
61 }
62
63 fn err_poisoned_lock(&self, e: Error<ErrTag>) {
64 error!(err!(e,
65 "{:?}: Another thread may have terminated while holding the lock.", self.id();
66 Lock, Poisoned));
67 self.inc_err();
68 }
69
70 fn error(&self, e: Error<ErrTag>) {
71 error!(e);
72 self.inc_err();
73 }
74
75 fn msg_unknown(&self, msg: M) {
76 error!(err!("{:?}: Message {:?} not recognised.", self.id(), msg; Invalid, Input));
77 self.inc_err();
78 }
79
80 fn result(&self, result: &Outcome<()>) {
81 match result {
82 Err(e) => self.error(e.clone()),
83 Ok(()) => (),
84 }
85 }
86
87 fn error_count(&self) -> Outcome<usize> {
88 let errc = self.errc();
89 let c = lock_mutex!(errc,
90 "{:?}: Cannot acquire the error counter lock, another thread may have \
91 terminated while holding the lock.", self.id());
92 Ok(*c)
93 }
94
95 fn inc_err(&self) {
96 let errc = self.errc();
97 match errc.lock() {
98 Err(_) => {
99 // This is bad.
100 error!(err!(
101 "{:?}: Cannot acquire the error counter lock.", self.id();
102 Lock, Poisoned));
103 },
104 Ok(mut c) => {
105 *c += 1;
106 if *c >= self.err_count_warning() {
107 // This is bad, and needs attention.
108 warn!("{:?}: this bot has triggered {} errors. This \
109 requires immediate attention.", self.id(), c);
110 }
111 },
112 }
113 }
114}