Sunday, November 18, 2012

Reading Records from Dart Dirty

‹prev | My Chain | next›

I am able to write to my dirt simple Dart datastore, affectionately known as dart-dirty. But a write-only local datastore is of little use. So today, it is time for this stuff to get real.

I am driving this development with Dart unit tests. I verified that writes were occurring by verifying that the datastore's size was increasing on write. Now, I need to be able to read back from the test datastore.

So I start with a test:
    test("can read a record from the DB", () {
      var db = new Dirty('test/test.db');
      db.set('everything', {'answer': 42});
      expect(
        db.get('everything'),
        equals({'answers': 42})
      );
    });
That fails, of course, because I do not have a get method:
FAIL: reading can read a record from the DB
  Caught NoSuchMethodError : method not found: 'get'
  Receiver: Instance of 'Dirty'
  Arguments: ["everything"]
  #0      Object.noSuchMethod (dart:core-patch:772:3)
  #1      test_read.<anonymous closure>. (file:///home/chris/repos/dart-dirty/test/dirty_test.dart:54:15)
...
Now that I am writing that, I realize that I should be using Dart operators for this stuff, but I'll change that another day. For now, I make my get method:
class Dirty {
  // ...
  void set(String key, value) {
    _docs[key] = value;
    // ...
  }

  dynamic get(String key) => _docs[key];
  // ...
}
And, since the set method is, among other things, building up the _docs HashMap, defining the get method is trivial. With that, I have three passing tests:
➜  dart-dirty git:(master) ✗ dart test/dirty_test.dart
unittest-suite-wait-for-done
PASS: new DBs creates a new DB
PASS: writing can write a record to the DB
PASS: reading can read a record from the DB

All 3 tests passed.
But more important than reading data from an in-memory store is the ability to read it from the filesystem. If node-dirty is any guide, I will eventually have to get moderately sophisticated with the manner in which old data is read from the filesystem (especially if there are many records). For my pass, I would like the simplest implementation possible.

It turns out that the implementation is easier than the test. For the implementation, I can add to the _load method of the Dirty class to read all the lines in the DB file:
  _load() {
    // ...
    var lines = db.readAsLinesSync();
    lines.forEach((line) {
      var rec = JSON.parse(line);
      _docs[rec['key']] = rec['val'];
    });
  }
The test for that is a huge pain. I need to await for the asynchronous close of the original DB, then wait for the asynchronous read of the new DB. Only then can I test my expectation that the key value pair that was originally written is in there again.

I am unsure if this is the best implementation of the test, but it works:
    test("can read a record from the DB stored on the filesystem", () {
      var db = new Dirty('test/test.db');
      db.set('everything', {'answer': 42});

      db.close(expectAsync0(() {
        var db2 = new Dirty(
          'test/test.db',
          expectAsync1((db3) {
            expect(
              db3.get('everything'),
              equals({'answer': 42})
            );
          })
        );
      }));

    });
Like I said, not pretty, but it works:
➜  dart-dirty git:(master) ✗ dart test/dirty_test.dart
unittest-suite-wait-for-done
PASS: reading can read a record from the DB stored on the filesystem

All 1 tests passed.
I call it a night there. I need all of this to behave more like a Dart Collection, so I will pick back up with that tomorrow.

Day #573

No comments:

Post a Comment