For the 'no-transaction change, while I don't like it, other than requiring both a database and transaction handle, the only idea I've come up with is to have okvs return a procedure.  When called, it returns the equivalent of the current transaction handle, so from the tutorial:

(define db (okvs '((home . "/tmp/wt") (create? . #t))))

(okvs-in-transaction db (lambda (txn) (okvs-set! txn (pack "hello") (pack "world"))))

becomes:

(okvs-in-transaction (db 'no-transaction) (lambda (txn) (okvs-set! txn (pack "hello") (pack "world"))))

or with less ceremony, but not clean to add a second operation and put both in a single transaction:

(okvs-set! (db 'no-transaction) (pack "hello") (pack "world"))))

Not elegant, especially whatever is the opposite of (db 'no-transaction), but maybe it'll help spark a better idea.

General comments on SRFI-167:

The Abstract should mention or imply its suitable for other types of storage engines, and mention it's suitable for general use of an OKVS.

In this sentence in the Rationale:

Ordered key-value stores offer a powerful set of simple and elegant primitives to build database abstractions, also sometimes called layers.

"also" and "sometimes" are redundant, dropping the latter would be good.

In the next sentence, the linked mention of the SRFI should append "-168" for situations where the link won't work, the hyperlink got lost, or whatever.  Might be better to use it more formally, "SRFI-168, Generic Tuple Store Database", or maybe with a colon.  More detailed mention of how SRFI-167 will work for any OKVS schema, including ones defined by other applications in other languages, would be good.  Hmmm, and an example of that would be good, what canonical uses of OKVSes are out there?

The last sentence of the Rationale needs a "the" between "compliments" and "generic", and like the above, appending "-168".

In Specification | Okvs and Transaction, there's the following sentences:

In the following, CONFIG is always an optional parameter that is an association list. Some configuration options are specified to ease portability.

Currently some options are suggested, but none are "specified".  This may change when explicit transactions become optional, in which case the latter sentence might be changed to "specified or suggested".

CONFIG is lower case for all function prototypes except okvs-range and okvs-prefix where it's upper case.

Consider renaming okvs to okvs-open, that's symmetrical with okvs-close, and makes what it does more obvious.

A hook style provision here and/or in SRFI-168 on opening a database to allow enforcement of constraints would be nice, that's a major reason I like the RDBMSes I've used in anger, DB2,  PostgreSQL, and Oracle.  I suggest it at this SRFI level because making it boilerplate here makes it more likely all Scheme applications will open a database with the constraints and thus better maintain data integrity.

The name of okvs-debug doesn't explain what it does, it could, for example, be a way of inserting hooks, or specifying tracing.  Something like okvs-map-(over-)all(-keys) would make it self-documenting.  While it's implicitly obvious, it should explicitly state that proc is a procedure that takes two arguments, a key and a value (bytevector).

Does okvs-debug do its thing in an implicit transaction like the okvs-prefix explicitly does when called with an empty bytevector prefix?

If you view it as a general vs. debug function, as the suggested name change suggests, adding range arguments or adding an additional function "-range" would make it more efficient for more uses.  I'm assuming that because operating on a range of keys is required in other functions, adding this wouldn't be onerous.

I can see people preferring to map over a subset of keys vs. using the generator approach, while SRFI-167 is oriented towards supporting SRFI-168, that's not the only way people will use it, especially if they're manipulating OKVSes with schema defined by other non-Scheme applications.  A further enhancement would be an optional predicate on key to check before calling proc, so retrieving every value is not required.

The documentation for okvs-transaction-begin says "The transaction must be associated with a newly created hash-table with the default comparator."  This is the first time and only time a comparator is mentioned, and the first time for hash-table, and they're not explained at all here or elsewhere.  Particularly a R7RS hash table that's supposed to do what?  It's necessary for a user to know this since okvs-transaction-metadata -> okvs-transaction-hash-table exposes the hash table (and I sense a potential for mischief...).

The "newly created" might imply you can only execute this function once, perhaps immediately after calling okvs/okvs-open, and before any calls to okvs-in-transaction.

It is not mentioned what happens if a transaction is not committed or rolled back, or if okvs-close is not called before the program exits.  Maybe say in okvs-close that this is "OKVS implementation dependent" since there are OKVSes that don't support transactions, and there might be ones that in practice fail to properly roll back.

okvs-transaction-metadata should indeed be renamed okvs-transaction-hash-table as previously discussed, and "Return the hash-table associated with TRANSACTION." is where the unexplained hash table gets problematic as mentioned above.

(okvs-transaction-commit transaction config) looks like it should be (okvs-transaction-commit transaction [config]).

The [failure [success]] options in okvs-in-transaction look like they would be *really* useful in the begin and rollback or commit transaction approach.  Perhaps only add them to okvs-transaction-begin to avoid Don't Repeat Yourself (DRY)?  The lack of [config] in okvs-in-transaction is another way these two methods for doing transactions aren't mirrored, if this is useful for them, it should be useful for okvs-in-transaction.

The use of "pair" and "pairs" in okvs-delete! and okvs-range-remove! should be prepended with "key-value" as it is in the other uses.

The okvs-range-remove! description should include the start-key, start-include?, end-key, and end-include? argument explanations of okvs-range transaction.

If okvs-maximum-key is not removed from the API, the result of trying to mutate it should be stated, for example raise an error or "undefined".

- Harold