#lang scheme/base
(require scheme/class
scheme/contract
srfi/26/cut)
(require "../snooze.ss"
"../snooze-interface.ss"
"cache.ss")
(define-persistent-struct audit-entity
([name (make-symbol-type #f #f 32)])
#:table-name 'auditentities)
(define entity-cache%
(class* object% (entity-cache<%>)
(init-field snooze)
(super-new)
(define forward-cache (make-hasheq))
(define reverse-cache (make-hasheq))
(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-hasheq))
(set! reverse-cache (make-hasheq)))
(define (memory-forward-lookup entity)
(hash-ref forward-cache entity #f))
(define (database-forward-lookup entity)
(send snooze find-one
(sql:select #:what ENTITY-id
#:from ENTITY
#:where (sql:= ENTITY-name (entity-table-name entity)))))
(define (memory-reverse-lookup id)
(hash-ref reverse-cache id #f))
(define (database-reverse-lookup id)
(schema-entity
(send snooze find-one
(sql:select #:what ENTITY-name
#:from ENTITY
#:where (sql:= ENTITY-id id)))))
(define (memory-store! id entity)
(hash-set! forward-cache entity id)
(hash-set! 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-out audit-entity)
entity-cache<%>
entity-cache%)