/iserver.rkt

http://github.com/elibarzilay/rudybot · Racket · 68 lines · 56 code · 7 blank · 5 comment · 3 complexity · 9595371d3ee9440e5b80d6edf733151f MD5 · raw file

  1. #lang racket
  2. (require
  3. (except-in "incubot.rkt" main)
  4. (only-in "vars.rkt" *incubot-logger*)
  5. (only-in "log-parser.rkt" utterance-text))
  6. (define (log fmt . args)
  7. (when (*incubot-logger*)
  8. (apply (*incubot-logger*) (string-append "incubot-server:" fmt) args)))
  9. (provide make-incubot-server)
  10. (define make-incubot-server
  11. (match-lambda
  12. [(? string? ifn)
  13. (with-handlers ([exn:fail:filesystem?
  14. (lambda (e)
  15. (log "Uh oh: ~a; using empty corpus" (exn-message e))
  16. (make-incubot-server (make-corpus)))])
  17. ;; Load the server up asynchronously, so we don't have to wait
  18. ;; for it.
  19. (let ([the-server (make-incubot-server (make-corpus))])
  20. (begin0
  21. the-server
  22. (thread
  23. (lambda ()
  24. (log "Reading log from ~a..." ifn)
  25. (time
  26. (with-handlers ([exn? (lambda (e)
  27. (log "Ooops: ~a~%" (exn-message e))
  28. (lambda ignored #f))])
  29. (call-with-input-file ifn
  30. (lambda (inp)
  31. (let/ec return
  32. (for ([(utterance i) (in-indexed (in-port read inp))])
  33. (the-server 'put (utterance-text utterance))
  34. (when (= i 100000)
  35. (return))))
  36. (log "Reading log from ~a...done~%" inp))))))))))]
  37. [(? corpus? c)
  38. ;; TODO, low priority: Racket threads have a built-in "mailbox",
  39. ;; which is essentially an async channel; we could replace one of
  40. ;; these channels with it.
  41. (let ([*to-server* (make-channel)]
  42. [*from-server* (make-channel)])
  43. (define funcs-by-symbol
  44. (make-immutable-hash
  45. `([get .
  46. ,(lambda (inp c)
  47. (channel-put *from-server* (incubot-sentence inp c))
  48. c)]
  49. [put .
  50. ,(lambda (sentence c)
  51. (channel-put *from-server* #t)
  52. (add-to-corpus sentence c))])))
  53. (thread
  54. (lambda ()
  55. (let loop ([c c])
  56. (match (channel-get *to-server*)
  57. [(cons symbol inp)
  58. (loop ((hash-ref funcs-by-symbol symbol) inp c))]))))
  59. (lambda (command-sym inp)
  60. (channel-put *to-server* (cons command-sym inp))
  61. (channel-get *from-server*)))]))