#lang mzscheme
(require scheme/class
scheme/contract
srfi/26/cut)
(require "../snooze-mzscheme.ss"
"../snooze-interface.ss"
"cache.ss")
(define/provide-persistent-struct audit-entity
([name (make-symbol-type #f #f 32)]))
(define entity-cache%
(class* object% (entity-cache<%>)
(init-field snooze)
(super-new)
(define forward-cache (make-hash-table))
(define reverse-cache (make-hash-table))
(define-alias ENTITY audit-entity)
(define/public (entity->id entity)
(cond [(memory-forward-lookup entity)
=> (lambda (id)
id)]
[(database-forward-lookup entity)
=> (lambda (id)
(memory-store! id entity)
id)]
[else (let ([id (database-store! entity)])
(memory-store! id entity)
id)]))
(define/public (id->entity id)
(cond [(memory-reverse-lookup id)
=> (lambda (entity)
entity)]
[(database-reverse-lookup id)
=> (lambda (entity)
(memory-store! id entity)
entity)]
[else (raise-exn exn:fail:snooze
(format "Entity not found in audit metadata: ~s" id))]))
(define/public (clear-cache!)
(set! forward-cache (make-hash-table))
(set! reverse-cache (make-hash-table)))
(define (memory-forward-lookup entity)
(hash-table-get forward-cache entity #f))
(define (database-forward-lookup entity)
(send snooze find-one
(q:select #:what ENTITY-id
#:from ENTITY
#:where (q:= ENTITY-name (entity-table-name entity)))))
(define (memory-reverse-lookup id)
(hash-table-get reverse-cache id #f))
(define (database-reverse-lookup id)
(schema-entity
(send snooze find-one
(q:select #:what ENTITY-name
#:from ENTITY
#:where (q:= ENTITY-id id)))))
(define (memory-store! id entity)
(hash-table-put! forward-cache entity id)
(hash-table-put! reverse-cache id entity))
(define (database-store! entity)
(define audit-entity
(send snooze save! (make-audit-entity (entity-table-name entity))))
(struct-id audit-entity))
(inspect #f)))
(provide-persistent-struct audit-entity (name))
(provide entity-cache<%>
entity-cache%)