rdfjs/N3.js

`removeMatches` removes quads from `Store` asynchronously

Closed this issue ยท 4 comments

When we remove quads from Store with removeMatches, they seem to stay in the Store until next tick. I'd expect them to be removed immediately. Also seems to be the case with deleteGraph.

You can see it reproduced in this code sandbox.

Example code

(async () => {
  const store = new n3.Store(); // new empty store

  console.log("number of quads in store:");

  console.log(store.size, "before addition"); // we expect 0 here, get 0

  store.add(
    new n3.Quad(
      new n3.NamedNode("https://subject"),
      new n3.NamedNode("https://predicate"),
      new n3.NamedNode("https://object"),
    ),
  );

  console.log(store.size, "after addition"); // we expect 1 here, get 1

  store.removeMatches(); // remove everything

  console.log(store.size, "synchronously after removal"); // we expect 0 here, get 1 <=== This is the problem

  await new Promise(process.nextTick); // wait for the next tick

  console.log(store.size, "next tick after removal"); // we expect 0 here, get 0
})();

Note that this library implements removeMatches as an event emitter; in particular it is implemented as follows

N3.js/src/N3Store.js

Lines 357 to 367 in d3faa57

removeMatches(subject, predicate, object, graph) {
const stream = new Readable({ objectMode: true });
stream._read = () => {
for (const quad of this.readQuads(subject, predicate, object, graph))
stream.push(quad);
stream.push(null);
};
return this.remove(stream);
}
.

So I would not expect the matches to be removed until the end event of the returned event emitter has been called.

Are there docs / types somewhere that indicate this should be synchronous?

It's because N3.js implements removeMatches as described in the RDF/JS Stream spec here.

I think the only sync solution is to call getQuads and then removeQuads with the result.

I've seen this comment by @RubenVerborgh:

The N3.Store interface is synchronous [...]

Which i guess is slightly incorrect, then.

I hadn't noticed the links to the external specs, thanks @joachimvh for pointing them out, and for the workaround.

Also, thank you all for promptly resolving this. ๐Ÿ™‚

Back in 2018 it was correct ๐Ÿ˜