right now notes is per-connection (is that correct?) so there may be
things that would break if the scope of notes were to change.

Well, $self->qp->connection->notes() is per-connection, $transaction->notes() is per-transaction, and (if/when my address notes patch is accepted), $addr->notes() is per address. But what if we give plugin authors access to hook_connection_notes, hook_transaction_notes, hook_address_notes, which passes the object in question, allowing the plugin to horse around with the note handling however it wants to, including widening the scope:

sub hook_transaction_notes_get {
    # store tarpit and some other thing in cache::fastmmap
    my ($self,$txn,$key) = @_;
    my %cfm_keys;
    @cfm_keys{qw(tarpit otherthing)} = ();
    return DECLINED unless exists $cfm_keys{$key};
    my $cache = Cache::FastMmap->new(...) or return DECLINED;
    return OK,$cach->get($key);
}

Possibly a hook_notes() could be provided to let you override all scopes of notes, either for convenience or for other strange purposes:

sub hook_notes_set {
    # I'm picky, so I want notes to be stored in {_my_notes}
    # rather than {_notes}, except for $connection objects
    my ($self,$obj,$key,$value)
    return DECLINED if ref $obj eq 'Qpsmtpd::Connection';
    $self->{_my_notes} = $value;
}

What kind of locking and/or transactioning do we want in persistent notes?

I suggest letting the backend handle both. Typically we'll be using something that was designed to let not just multiple QP processes but also multiple non-QP processes interact with the store, and so it already has to implement its own locking and atomicity. If we absolutely need to implement our own, we can do so in the plugin.

-Jared

Reply via email to