Hey,
In openair, I'm getting problems with dead instances. I think its maybe because I'm working against cells.
What I need to do is keep track somewhere of all the nodes that change in response to a request. Currently, this is done using an "update" slot which we setf on an xhtml observer.
(defobserver xhtml ((self html)) (when (and new-value (do-send self new-value old-value)) (trc "new xhtml" new-value) (setf (update self) (format nil "$("#~a").replaceWith("~a")" (md-name self) (js-escape new-value)))))
When a new request comes in, we do the following:
- walk the family tree, setting the update slot to nil. - feed the request parameters into the model - walk the family tree looking for places where update is not nil and sending it to the browser
In some cases, that works fine but in others, we find dead cells while walking the tree the first time.
Another point to note is that the update slot is specified as :cell nil. Based on its purpose and usage, does that make sense?
Should I be wrapping this traversal in with-integrity or something?
Cheers, Andy
Andy Chambers wrote:
Hey,
In openair, I'm getting problems with dead instances. I think its maybe because I'm working against cells.
Maybe, maybe not. I get this all the time, and although many times I can find a way to re-express my problem to avoid dead instances I would love to make this easier. Naturally and sensibly written code leads to dead instances, and we want that kind of code to Just Work, not make the programmer stop and scratch their head for an hour working around it. But for now....
What I need to do is keep track somewhere of all the nodes that change in response to a request. Currently, this is done using an "update" slot which we setf on an xhtml observer.
(defobserver xhtml ((self html)) (when (and new-value (do-send self new-value old-value)) (trc "new xhtml" new-value) (setf (update self) (format nil "$("#~a").replaceWith("~a")" (md-name self) (js-escape new-value)))))
When a new request comes in, we do the following:
- walk the family tree, setting the update slot to nil.
- feed the request parameters into the model
- walk the family tree looking for places where update is not nil
and sending it to the browser
In some cases, that works fine but in others, we find dead cells while walking the tree the first time.
(1) Do you mean dead instances or dead Cells? (2) If instances, and if the tree is a cells-mediated tree, ie family/.kids, it is not clear to me how dead children instances would be encountered.
What I see a lot is that I have a blinking edit caret watching the application focus and then the student quits a quiz and returns to the quiz menu. If I do not have code all over the map clearing the application focus the edit caret (a global thing, perhaps my real problem) ends up looking at a dead instance on the next blink. But that is because the application focus is an input Cell setf'ed by application code (setf being the root of all evil).
It is not always easy, but have you ever spent an hour trying to figure out how this actually happens? Exactly why does the traversal lead to a dead instance? Was someone keeping a reference to someone else instead of going thru channels (an fm-find)?
Another possibility may have to do with stuff forever coming and going as rules re-run and create all new instances even when just a small bit of the graph actually needs adding or removing. That /should/ work, but if you are keeping references to nodes such churning will break your code faster. Here again, tho, the problem would be keeping long-lived references vs. always going and looking for stuff such that only current instances get encountered.
To summarize, it /is/ a problem in general but I would like to know exactly how you hit these dead instances because it will change what I recommend.
FYI, one thing I am having luck with is a heavy hammer: md-slot-value not returning any value it sees is an MDEAD (sorry, that was just a debugging function at first, should be md-dead? or md-deadp) instance and returning nil when asked for any slot of an MDEAD instance. But that of course wll not always work, so let's not consider these until we understand exactly how deads are bein hit.
Another point to note is that the update slot is specified as :cell nil. Based on its purpose and usage, does that make sense?
Yes.
Should I be wrapping this traversal in with-integrity or something?
Hmmm. Hang on. Digression: Are you using lazy cells? Sorry, I forgot the details. If so, just traversing the tree and reading lazy cells will trigger Cells stuff and observers etc etc. Anyway, no, a toplevel model perturbation gets silently wrapped in with-integrity. It is necessary (as I say, even a read can kick off change) but I managed to hide that from the developer. Same goal: Cells should be as easy to live with as they are functionally powerful, or we are just replacing one hassle with another.
kt