storage.rst 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. =========
  2. Storage
  3. =========
  4. The storage systems attached to your app
  5. ----------------------------------------
  6. Dynamic content: queue_store and public_store
  7. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  8. Two instances of the StorageInterface come attached to your app. These
  9. are:
  10. + **queue_store:** When a user submits a fresh piece of media for
  11. their gallery, before the Processing stage, that piece of media sits
  12. here in the queue_store. (It's possible that we'll rename this to
  13. "private_store" and start storing more non-publicly-stored stuff in
  14. the future...). This is a StorageInterface implementation
  15. instance. Visitors to your site probably cannot see it... it isn't
  16. designed to be seen, anyway.
  17. + **public_store:** After your media goes through processing it gets
  18. moved to the public store. This is also a StorageInterface
  19. implelementation, and is for stuff that's intended to be seen by
  20. site visitors.
  21. The workbench
  22. ~~~~~~~~~~~~~
  23. In addition, there's a "workbench" used during
  24. processing... it's just for temporary files during
  25. processing, and also for making local copies of stuff that
  26. might be on remote storage interfaces while transitionally
  27. moving/converting from the queue_store to the public store.
  28. See the workbench module documentation for more.
  29. .. automodule:: mediagoblin.tools.workbench
  30. :members:
  31. :show-inheritance:
  32. Static assets / staticdirect
  33. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  34. On top of all that, there is some static media that comes bundled with your
  35. application. This stuff is kept in:
  36. mediagoblin/static/
  37. These files are for mediagoblin base assets. Things like the CSS files,
  38. logos, etc. You can mount these at whatever location is appropriate to you
  39. (see the direct_remote_path option in the config file) so if your users
  40. are keeping their static assets at http://static.mgoblin.example.org/ but
  41. their actual site is at http://mgoblin.example.org/, you need to be able
  42. to get your static files in a where-it's-mounted agnostic way. There's a
  43. "staticdirector" attached to the request object. It's pretty easy to use;
  44. just look at this bit taken from the
  45. mediagoblin/templates/mediagoblin/base.html main template:
  46. <link rel="stylesheet" type="text/css"
  47. href="Template:Request.staticdirect('/css/extlib/text.css')"/>
  48. see? Not too hard. As expected, if you configured direct_remote_path to be
  49. http://static.mgoblin.example.org/ you'll get back
  50. http://static.mgoblin.example.org/css/extlib/text.css just as you'd
  51. probably expect.
  52. StorageInterface and implementations
  53. ------------------------------------
  54. The guts of StorageInterface and friends
  55. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  56. So, the StorageInterface!
  57. So, the public and queue stores both use StorageInterface implementations
  58. ... but what does that mean? It's not too hard.
  59. Open up:
  60. mediagoblin/storage.py
  61. In here you'll see a couple of things. First of all, there's the
  62. StorageInterface class. What you'll see is that this is just a very simple
  63. python class. A few of the methods actually implement things, but for the
  64. most part, they don't. What really matters about this class is the
  65. docstrings. Each expected method is documented as to how it should be
  66. constructed. Want to make a new StorageInterface? Simply subclass it. Want
  67. to know how to use the methods of your storage system? Read these docs,
  68. they span all implementations.
  69. There are a couple of implementations of these classes bundled in
  70. storage.py as well. The most simple of these is BasicFileStorage, which is
  71. also the default storage system used. As expected, this stores files
  72. locally on your machine.
  73. There's also a CloudFileStorage system. This provides a mapping to
  74. [OpenStack's swift http://swift.openstack.org/] storage system (used by
  75. RackSpace Cloud files and etc).
  76. Between these two examples you should be able to get a pretty good idea of
  77. how to write your own storage systems, for storing data across your
  78. beowulf cluster of radioactive monkey brains, whatever.
  79. Writing code to store stuff
  80. ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  81. So what does coding for StorageInterface implementations actually look
  82. like? It's pretty simple, really. For one thing, the design is fairly
  83. inspired by [Django's file storage API
  84. https://docs.djangoproject.com/en/dev/ref/files/storage/]... with some
  85. differences.
  86. Basically, you access files on "file paths", which aren't exactly like
  87. unix file paths, but are close. If you wanted to store a file on a path
  88. like dir1/dir2/filename.jpg you'd actually write that file path like:
  89. ['dir1', 'dir2', 'filename.jpg']
  90. This way we can be *sure* that each component is actually a component of
  91. the path that's expected... we do some filename cleaning on each component.
  92. Your StorageInterface should pass in and out "file like objects". In other
  93. words, they should provide .read() and .write() at minimum, and probably
  94. also .seek() and .close().