core-async

jlmr 2020-01-26T16:36:21.251100Z

Hi, I’m struggling with a bug. I’ve tried to make a minimal example of the code. When running this code I can see from the tap> that sometimes cache resets to an empty map {}. Anyone have an idea what I’m doing wrong?

(let [in (chan)
      tags [:some :list :of :tags]
      f some-function]

  (go-loop [cache {}]
    (let [{:keys [tag payload]} (<! in)
          new-cache (assoc cache tag payload)
          result (apply f (for [tag tags] (get new-cache tag)))]

      (tap> {:cache cache
             :new-cache new-cache
             :result result})

      (recur new-cache)))
  in)

2020-01-26T16:48:17.253800Z

Have you restarted your repl recently? My guess is you have some other code running, maybe an earlier version of that loop

jlmr 2020-01-26T16:50:27.254700Z

@hiredman have restarted many times since finding this bug. Pretty sure that’s not the problem

2020-01-26T16:52:39.256700Z

It kind of has to be. What did does that tap result look like that is making you thing cache is becoming {} ?

2020-01-26T16:55:40.260900Z

Are you seeing {} in that tap output and concluding that cache has become {} when in fact that would be {:cache {} :new-cache ... :new-result ...} ?

jlmr 2020-01-26T16:56:30.261800Z

@hiredman yes but also :new-cache seems to reset

jlmr 2020-01-26T16:56:43.262300Z

Or am I misinterpreting something?

2020-01-26T16:59:21.265Z

Are you sure you are looking at the correct file? I've seen people edit one copy and run another. Are you sure you are saving the file after edits?

jlmr 2020-01-26T17:02:08.268300Z

What effect would saving the file have?

2020-01-26T17:02:32.268600Z

You can put an (assert nil) at the top of the loop to determine if that code is actually being run, and an (assert (not-empty? new-cache)) later on in the loop to determine if that loop is the source of those tap messages

2020-01-26T17:02:43.269Z

I dunno how you are running all this

2020-01-26T17:03:33.270300Z

If you are telling your editor to eval the file, it may load the file from disk instead of the contents of the unsaved buffer

jlmr 2020-01-26T17:04:26.271600Z

I’m using chlorine and it’s command to evaluate a specific form. But I will try your suggestions to make sure I’m looking at the right code.

2020-01-26T17:06:36.274Z

The assert nil will cause an error if the code you are looking at is actually run, then you can remove it, and then the asset not empty will fire if new cache ever does become empty in that code

2020-01-26T17:06:54.274600Z

Are you sure you have actually restarted your repl?

2020-01-26T17:07:39.275700Z

Does chlorine just keep a repl around and opening and closing the repl window or whatever just reconnects you to it?

jlmr 2020-01-26T17:09:09.276200Z

It connects to a running socket REPL.

jlmr 2020-01-26T17:09:36.277100Z

The repl keeps going even if you close Atom. It’s started in a terminal window

jlmr 2020-01-26T17:10:26.278500Z

Could be that my minimal example doesn’t show enough to pinpoint the problem

2020-01-26T17:10:50.279Z

Ah

2020-01-26T17:11:30.280100Z

I didn't catch that that isn't what is actually breaking

2020-01-26T17:12:13.281Z

If you actual code is building the cache with something more complicated then assoc the problem is likely there

2020-01-26T17:12:49.282200Z

Is it an actual cache with ttls? Then becoming empty has to be expected behavior

jlmr 2020-01-26T17:12:53.282500Z

Nope that part is the same as the actual code. The assoc I mean

jlmr 2020-01-26T17:14:21.283100Z

It’s just a regular map that I associate into

jlmr 2020-01-26T17:15:42.284700Z

The only thing thats missing from my example is that i put (`>!`) result on some channels

2020-01-26T17:16:55.286700Z

In the example code, cache only grows in size, which is kind of atypical for a cache, is there any code at all that removes or expires entries

2020-01-26T17:18:39.287600Z

I guess is doesn't grow beyond a constant size, the number of tags, in the example

jlmr 2020-01-26T17:20:45.289700Z

The number of tags is indeed constant. It just takes the most recent value with the tag, assocs it into the cache and reruns the function f using all the values in the cache.

jlmr 2020-01-26T17:21:00.290200Z

And the result is put on some channels

2020-01-26T17:24:29.294200Z

I can't debug it without more information, either more detail of the real code, or the results of the asserts I suggested. I strongly recommend finding your invariants like new cache is always greater than or equal to cache in size, and asserting it in as many places as possible in code you are debugging

2020-01-26T17:25:32.295200Z

Because what you are looking for is the first place that invariant is violated

jlmr 2020-01-26T17:54:38.296Z

Will try some more things tomorrow and check back here if needed. Thanks for the tips!