We decided to move the discussion here. Here is a (very) lightly abridged transcript of the discussion so far.
[We had been talking about the Stage Pi control logic.]
hamishmb wrote:07/09/2020, 13:18Only question I think I have is what if the database goes down while a valve is open? But I think other parts of the framework may need improvements to deal with that.
PatrickW wrote:07/09/2020, 13:44I didn't think of DB failure handling. Is it even possible to close a valve if the DB is down? I suppose the valve would have to do that itself after a timeout. I think my intention was for the logic to 'hang' in its current state if it can't get valid sensor readings. [...] If it can get sensor readings but cannot control a necessary device, then it can do no more than monitor the situation.
hamishmb wrote:07/09/2020, 13:55No actually, the valve would have to do that itself. It's just making sure anything local like a pump connected directly to the pi would be turned off, so yeah you're right, never mind.
hamishmb wrote:07/09/2020, 13:55Terry was saying that remembering the last few readings/state could help, but for G6 I don't think it'd change anything.
PatrickW wrote:07/09/2020, 16:41Yes, if it is relying on a cache of old readings, it will just decide to stay in the current state until they change, the effect of which is the same as what it already does. I suppose previous readings might let it detect when a water level isn't changing the way it should be, but only if it takes into account the actions of the other algorithms.
PatrickW wrote:07/09/2020, 16:45But previous readings are already available when the database is working.
PatrickW wrote:07/09/2020, 16:50Should get_latest_reading be able to fall back to using local data if the database is down? That would be enough to keep sump pi running.
PatrickW wrote:07/09/2020, 16:56To keep that clean, I would have a separate local get_latest_reading function/method and then another get_latest_reading that tries the database one or falls back to the local one.
hamishmb wrote:07/09/2020, 17:17That'd be a good idea, something to go in logiccoretools? Then it can be seamless.
hamishmb wrote:07/09/2020, 17:17Best to wait until after the merge I think - that's kinda a separate work item, and we don't really need to delay things to do that.
hamishmb wrote:08/09/2020, 23:34Just realised that your code is using the database to fetch readings from the probes connected directly to Stage Pi. This will work but be a bit inefficient and depends on the NAS box when it need not. That's okay for here, but for sites with pumps and other devices it'd be best if we could still control those based on local readings if the NAS box/network goes down for some reason
PatrickW wrote:08/09/2020, 23:45I think I asked about this when I began to switch it [the Stage Pi logic] over to logiccoretools. I understood that everything was going via the database, but perhaps I misunderstood. What is the intended method for obtaining local readings? In practice, Stage Pi can't really do anything without readings from Wendy Butts Pi or control of V12, so loss of NAS will always grind it to a halt.
hamishmb wrote:09/09/2020, 12:42The intended way is to use the readings dictionary passed to the control logic function. This will require making the main loop a bit less stupid than it is right now. I'm sorry because this is my fault for being unclear, that is indeed what you asked, but I didn't realise you were asking about local readings too.
hamishmb wrote:09/09/2020, 12:43Again, we can do that after merging, because your code is, as you say, fully functional.
PatrickW wrote:09/09/2020, 12:50Oh, I already removed all the readings dictionary code from Stage Pi's logic, because I thought the readings dictionary was going away. I don't particularly like having two separate ways of getting readings. It seems to me as though logiccoretools should do that automatically, but we can cross that bridge later on.
PatrickW wrote:09/09/2020, 12:51Readings dict will make unit testing more complex.
hamishmb wrote:09/09/2020, 12:53Yeah, point. How about this:
hamishmb wrote:09/09/2020, 12:55This is seamless and means existing code need not change. Again, we can do that later on
hamishmb wrote:09/09/2020, 12:55logiccoretools can automatically stash the last few readings for each probe, and if the call to DatabaseConnection fails, it can just return the newest one it had instead (or if you asked for multiple readings, it can do its best to do what you asked)
(Patrick apparently doesn't read the suggestion properly.)hamishmb wrote:09/09/2020, 12:55Does that sound better?
PatrickW wrote:09/09/2020, 13:51Why can't it just get the actual readings if they are local readings? It could just go 'Oh, DB is down. What does the readings dict say then?' This kind of thing was the rationale behind using logiccoretools instead of directly using DatabaseConnection: you can slip in a different way of doing things without changing either DatabaseConnection or the control logic. (N.B This seems like a good point to mention that I was thinking the functions in logiccoretools would be empty variables (= None), and then run_standalone could assign the appropriate function to each variable, and unit tests would assign a different, fake set. So, if we just want DB access it would assign each of DatabaseConnection's methods to the variables. If we want a version that tries the DB but falls back on local readings, that's a separate set of functions, somewhere in Tools, that can be assigned to the logiccoretools variables.)
hamishmb wrote:09/09/2020, 13:54That's pretty much what I was suggesting (readings wise). What's the advantage of doing this with run_standalone()? It seems overcomplicated and unnecessary for me. We can override them anyway in the unit tests so it doesn't obstruct testing (I've done this in many places in my tests). Does it make more sense to have it fall back automatically? Why would we ever want it not to fall back?
hamishmb wrote:09/09/2020, 13:54Also, should we discuss this on the forum so Terry and co can see the messages?
hamishmb wrote:09/09/2020, 13:55That way we have a better record of why we picked this design and why we discarded other ideas
(Unable to suppress a sudden thought, Patrick then continues texting...)PatrickW wrote:09/09/2020, 13:59Yes, I would prefer to discuss this on the forum for that reason and because texting is making my little finger numb!
PatrickW wrote:09/09/2020, 14:06I think having a default behaviour for the functions is likely to encourage coding against the default behaviour rather than against the abstract interface.
PatrickW wrote:09/09/2020, 14:09There could be a logiccoretools.setup_functions_db(), etc. to quickly assign a particular set of functions without making other parts of the code remember which ones go together.
Hamish asked me to summarise, but I thought I may as well just post a transcript to avoid misrepresenting what was said.hamishmb wrote:09/09/2020, 14:10If we make the fallback behave exactly the same to the knowledge of anything using the function, it shouldn't matter? Let's discuss on the forum anyway