You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
2.4 KiB

4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
3 years ago
3 years ago
3 years ago
4 years ago
  1. # vim: set fileencoding=utf-8 :
  2. """provide a trivial way to send messages between processes
  3. messages are being sent as files to an inbox, which is a path of a directory,
  4. using a filename as a marker
  5. recv_all() is delivering all messages, which are newer than the marker file
  6. after completion reading is touching the marker file
  7. to re-read messages touch the marker file with an older timestamp or just
  8. delete the marker file to re-read all messages
  9. """
  10. # Minimail 1.2
  11. # Copyleft 2019, 2020, p≡p foundation
  12. # this file is under GNU General Public License 3.0
  13. import os
  14. from secrets import token_urlsafe
  15. from time import sleep
  16. from random import random
  17. # set timing to None for random timing
  18. timing = None
  19. def snooze():
  20. if timing is None:
  21. sleep(random()/2)
  22. else:
  23. sleep(timing)
  24. def unlock(inbox):
  25. "clear the inbox from lockfile"
  26. lockfile = inbox / "lock"
  27. try:
  28. lockfile.unlink()
  29. except:
  30. pass
  31. class Lock:
  32. "lock inbox context to be used by with statement"
  33. def __init__(self, inbox):
  34. self.inbox = inbox
  35. def __exit__(self, *exc):
  36. unlock(self.inbox)
  37. def __enter__(self):
  38. lockfile = self.inbox / "lock"
  39. while lockfile.is_file():
  40. snooze()
  41. lockfile.touch()
  42. def send(inbox, msg, marker):
  43. "send msg to inbox in MIME format"
  44. snooze()
  45. with Lock(inbox):
  46. name = marker + "_" + token_urlsafe(16) + ".eml"
  47. with open(inbox / name, "wb") as f:
  48. f.write(str(msg).encode())
  49. def newer(file, stamp):
  50. "return True if file is newer than timestamp stamp"
  51. if not file.is_file():
  52. return False
  53. if stamp is None:
  54. return True
  55. stat = file.stat()
  56. return stat.st_mtime > stamp.st_mtime
  57. def recv_all(inbox, marker):
  58. """receive a list of new MIME messages from inbox, which are newer than the
  59. marker file"""
  60. r = []
  61. while not r:
  62. with Lock(inbox):
  63. try:
  64. stamp = (inbox / marker).stat()
  65. except:
  66. stamp = None
  67. l = [ path for path in inbox.glob("*.eml") ]
  68. (inbox / marker).touch(exist_ok=True)
  69. for p in reversed(l):
  70. if newer(p, stamp):
  71. with open(p, "rb") as f:
  72. txt = f.read(-1)
  73. r.append((p, txt))
  74. if not r:
  75. snooze()
  76. return r