A place to cache linked articles (think custom and personal wayback machine)
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.

index.html 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang="fr">
  4. <!-- Has to be within the first 1024 bytes, hence before the `title` element
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset="utf-8">
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name="viewport" content="width=device-width,initial-scale=1">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Understanding A Protocol (archive) — David Larlet</title>
  13. <meta name="description" content="Publication mise en cache pour en conserver une trace.">
  14. <!-- That good ol' feed, subscribe :). -->
  15. <link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
  16. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  17. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
  18. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
  19. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
  20. <link rel="manifest" href="/static/david/icons2/site.webmanifest">
  21. <link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
  22. <link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
  23. <meta name="msapplication-TileColor" content="#f7f7f7">
  24. <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
  25. <meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
  26. <meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
  27. <!-- Documented, feel free to shoot an email. -->
  28. <link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
  29. <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
  30. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  31. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  32. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  33. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  34. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  35. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  36. <script>
  37. function toggleTheme(themeName) {
  38. document.documentElement.classList.toggle(
  39. 'forced-dark',
  40. themeName === 'dark'
  41. )
  42. document.documentElement.classList.toggle(
  43. 'forced-light',
  44. themeName === 'light'
  45. )
  46. }
  47. const selectedTheme = localStorage.getItem('theme')
  48. if (selectedTheme !== 'undefined') {
  49. toggleTheme(selectedTheme)
  50. }
  51. </script>
  52. <meta name="robots" content="noindex, nofollow">
  53. <meta content="origin-when-cross-origin" name="referrer">
  54. <!-- Canonical URL for SEO purposes -->
  55. <link rel="canonical" href="https://aeracode.org/2022/12/05/understanding-a-protocol/">
  56. <body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">
  57. <article>
  58. <header>
  59. <h1>Understanding A Protocol</h1>
  60. </header>
  61. <nav>
  62. <p class="center">
  63. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  64. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  65. </svg> Accueil</a> •
  66. <a href="https://aeracode.org/2022/12/05/understanding-a-protocol/" title="Lien vers le contenu original">Source originale</a>
  67. </p>
  68. </nav>
  69. <hr>
  70. <p>Yesterday I pushed out the <a href="https://docs.jointakahe.org/en/latest/releases/0.5/">0.5.0 release of Takahē</a>,
  71. and while there's plenty left to do, this release is somewhat of a milestone
  72. in its own right, as it essentially marks the point where I've implemented
  73. enough of ActivityPub to shift focus.</p>
  74. <p>With the implementation of image posting in this release, there are now only
  75. a few things left at a <em>protocol</em> level that I know I'm missing:</p>
  76. <ul>
  77. <li>
  78. <p>Custom emoji (these are custom per-server and a mapping of name-to-image
  79. comes with each post)</p>
  80. </li>
  81. <li>
  82. <p>Reply fan-out to the original author's followers</p>
  83. </li>
  84. <li>
  85. <p>Pinned posts on profiles (and collections in general)</p>
  86. </li>
  87. <li>
  88. <p>Shared inbox delivery (to reduce fan-out requests)</p>
  89. </li>
  90. </ul>
  91. <p>My current aim is to get Takahē to a point where a few small communities can
  92. run on it (including takahe.social), and while these are nice,
  93. they are not critical for that. The reply fan-out is probably most important,
  94. but is also the easiest given what we have written already.</p>
  95. <p>Instead, it's now time to shift and focus on stability and efficiency. My
  96. general tactic for big new projects like this is an initial "spike" period,
  97. where I am more focused on pushing out code with a roughly correct architecture
  98. rather than focusing on query efficiency, caching or the like, and to then
  99. shift gears into more of a "polish" period.</p>
  100. <p>Takahē is actually pretty useable for me as a daily driver for
  101. the <a href="https://takahe.social/@takahe@jointakahe.org/">@takahe@jointakahe.org</a>
  102. account - sure, I find a few bugs here or there, but it's honestly not bad.
  103. That means, to me, it's time to shift focus a bit more towards polishing.</p>
  104. <p>The other big missing feature for a community at this point is probably having
  105. mobile app support (which I plan to do by implementing a Mastodon-compatible
  106. client API) and better moderation features (reporting and user blocking,
  107. in addition to the existing server blocking).</p>
  108. <p>So, I'm going to focus on adding those, polishing, and improving efficiency; there's now
  109. quite a few other contributors to the project who have been helping out
  110. with bugfixes, efficiency, and plenty more, which is helping a great deal.</p>
  111. <p>I'll also be sending out a few
  112. invitations to <a href="https://takahe.social">takahe.social</a> to use that as a testbed
  113. as the first small community; nothing like dogfooding your own software to see
  114. what it needs (as well as asking some existing Mastodon admins for their
  115. thoughts, if they are gracious enough to lend me some of their time).</p>
  116. <p>Still, though, getting to this point is quite a big deal - I feel like I've
  117. learned a lot about ActivityPub and its related specifications by implementing
  118. them. So let's talk about it a little bit.</p>
  119. <h2>Fan-Out</h2>
  120. <p>ActivityPub is all about "fan-out" - the process of getting posts from their
  121. authors to their followers. At the basic level, this means one HTTP request
  122. per follower to deliver it to their inbox - but there's some efficiency gains
  123. to be made with "shared inboxes", where you can push things on a per-server
  124. basis rather than per-user.</p>
  125. <p>Obviously, doing this is noisy and takes a lot of requests, and has to be done
  126. as background workers - especially as the server on the other end might be
  127. down when you try and send the message over, and you need to retry.</p>
  128. <p>Plus, whenever you reply to someone, that reply is then sent to every one of
  129. their followers so that it can appear in reply threads. This means there's an
  130. increasing amplification effect as you get more and more followers, and your
  131. server spends a lot of its life just sending request and getting requests from
  132. other servers.</p>
  133. <p>There's other aspects to fan-out, though; there was an
  134. <a href="https://ar.al/2022/11/09/is-the-fediverse-about-to-get-fryed-or-why-every-toot-is-also-a-potential-denial-of-service-attack/">excellent blog post</a>
  135. about that last month that outlines the problems with link previews. See, when
  136. you post a message to a server's inbox, Mastodon (at least) goes and fetches
  137. any image attachments, and tries to generate web previews for any links. If
  138. people have mobile clients, some of those will <em>also</em> try to fetch previews.
  139. This does not end well for unprepared servers - and for those links, they
  140. could just be someone's random blog.</p>
  141. <p>Takahē does not do this prefetching yet - we'll likely never do it for the
  142. link previews (but some clients connected to us will, once there's a client API).
  143. Post attachments and profile images are a different story - we need to at
  144. least proxy those for user privacy, but we can hopefully make it a caching
  145. proxy. If users have their timelines open, there's not a big difference between
  146. a caching proxy and prefetching for the source server, either.</p>
  147. <p>How do we solve this? Well, bundling some of this data into the original post
  148. is one idea; having shared caching proxies split between multiple servers is
  149. another potential one as well.</p>
  150. <p>That brings us, though, to the push-pull of scaling that's at the heart of
  151. ActivityPub.</p>
  152. <h2>Two Axes Of Scaling</h2>
  153. <p>In a previous post about ActivityPub and Takahē, I referred to the fact that
  154. there are two "axes" of scaling available in the protocol:</p>
  155. <ul>
  156. <li>Having more people per server/instance</li>
  157. <li>Running more servers/instances</li>
  158. </ul>
  159. <p>Both of these have their pros and cons, and it's hard to go all in on one of
  160. them - having a million people on one server is difficult to scale for that
  161. individual server (you have to start building it as its own distributed
  162. system), but having a million servers makes the fan-out problem even worse
  163. (say hello to massive prefetching loads and shared inboxes being not very
  164. useful).</p>
  165. <p>It seems to me like a bit of a separation between domain, moderator, and
  166. caching store is needed - Takahē already lets multiple domains be on a single
  167. server, but the server moderation and caching are scoped just to that one server.</p>
  168. <p>I do believe that sharing moderation across domains is a very important scaling
  169. step; this doesn't have to purely be "multiple domains on the same server",
  170. either - I think there's scope for a moderation API where you can have a
  171. team of professional (volunteer or paid) moderators look after multiple
  172. servers.</p>
  173. <p>Sharing caching and previews is also important, though; if there was just ten
  174. or so link preview caches around, and all servers used one of them, then we
  175. still avoid centralisation while massively lowering the load on the target
  176. of links.</p>
  177. <h2>That Transport Layer</h2>
  178. <p>I both love that ActivityPub is all over HTTP, and hate it.</p>
  179. <p>On the plus side, it means there's all manner of pre-existing load balancers,
  180. gateways, frameworks and more at our disposal. Plus, every programming language
  181. on Earth has some way of slinging JSON over HTTP.</p>
  182. <p>On the negative side, it's wildly inefficient. There's a lot of overhead for
  183. each individual call, <code>Accept</code> headers have to be bandied around everywhere,
  184. and there's a lot of HTTP implementation variation that has to be accounted for.</p>
  185. <p>If, magically, I could change it - would I go to something like SMTP, with its
  186. own port and protocol? I'm not entirely sure, to be honest - I do like the ease
  187. of entry with HTTP, and it does mean there's a lot of framing and encoding
  188. already agreed. Maybe HTTP as a base protocol with an optional TCP alternate
  189. for high-traffic servers to talk to each other over.</p>
  190. <p>The one thing I would get rid of, though, is JSON-LD. If you're not aware,
  191. ActivityPub is not just JSON - it's JSON-LD, which has schemas, namespaces,
  192. expanded and compressed forms, transforms, and all manner of other stuff.
  193. You need to transform each message to a canonical form before you parse it!</p>
  194. <p>I get the idea, but I was never an RDF fan (it's just JSON RDF, basically) and
  195. it just makes everything so much more complex. A plain
  196. JSON specification with known keys would have been better, I think, though
  197. I was not there when the spec was written, so I'm sure there's more context
  198. I lack.</p>
  199. <p>I do want to stress, though, that while I am not a huge fan of the transport
  200. layer, I think the object model is quite decent. If we could get
  201. <code>preferredDomain</code> in there along with some proper multi-size image support,
  202. I would be even happier than my usual buoyant self.</p>
  203. <h2>Difference Is Strength</h2>
  204. <p>A virtual Mastodon monopoly is not good for almost anyone, I think - I'm
  205. actually quite excited for Tumblr to implement ActivityPub, because it stands
  206. a chance of forcing protocol changes and improvements to be discussed,
  207. rather than directed almost entirely by one project.</p>
  208. <p>If we can get Takahē to even 5% of active users on the Fediverse, that would
  209. be a significant impact, too. I'm not sure we'll get there, but I do at least
  210. hope the attempt will also place its own bit of pressure on the protocol in
  211. terms of evolving and trying to fix some of the scaling issues we're all
  212. sailing directly towards.</p>
  213. <p>How to do that responsibly is another question - I would ideally like to make
  214. sure we have a server that is designed to easily handle things like DMCA
  215. requests, GDPR requests, and the awful spectre of terrorist content and CSAM.
  216. I'm looking into starting a fund to pay for some legal and compliance
  217. consultations on this front; it's the sort of work that
  218. every admin should not have to do themselves, and I'd love us to have a server
  219. designed to handle the requirements easily, and written guides as to how to do it.</p>
  220. <p>Still, for me, the focus right now is on growing Takahē and hopefully fostering some
  221. communities under its wing, and that means getting stability, efficiency,
  222. and working closely with people who want to use us to run communities. It's
  223. also about slowly fostering a set of people who look after it with sensible
  224. governance, so I'm not needed as a decision-making leader forever.</p>
  225. <p>I'm not yet focused on people migrating servers from Mastodon - supporting
  226. that is eventually on the roadmap, and I've reserved the appropriate URL
  227. patterns so actor/object URLs can move over seamlessly, but it's still a lot
  228. of work, and we're not ready for that quite yet.</p>
  229. <p>If you're interested in helping out with Takahē, do pop over to our
  230. <a href="https://discord.gg/qvQ39tAMvf">Discord</a> or email me at andrew@aeracode.org
  231. and mention what you'd like to help out with - there's a large
  232. <a href="https://docs.jointakahe.org/en/latest/contributing/">number of areas</a> we need
  233. help with, not just coding!</p>
  234. </article>
  235. <hr>
  236. <footer>
  237. <p>
  238. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  239. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  240. </svg> Accueil</a> •
  241. <a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
  242. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
  243. </svg> Suivre</a> •
  244. <a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
  245. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
  246. </svg> Pro</a> •
  247. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
  248. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
  249. </svg> Email</a> •
  250. <abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
  251. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
  252. </svg> Légal</abbr>
  253. </p>
  254. <template id="theme-selector">
  255. <form>
  256. <fieldset>
  257. <legend><svg class="icon icon-brightness-contrast">
  258. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
  259. </svg> Thème</legend>
  260. <label>
  261. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  262. </label>
  263. <label>
  264. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  265. </label>
  266. <label>
  267. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  268. </label>
  269. </fieldset>
  270. </form>
  271. </template>
  272. </footer>
  273. <script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
  274. <script>
  275. function loadThemeForm(templateName) {
  276. const themeSelectorTemplate = document.querySelector(templateName)
  277. const form = themeSelectorTemplate.content.firstElementChild
  278. themeSelectorTemplate.replaceWith(form)
  279. form.addEventListener('change', (e) => {
  280. const chosenColorScheme = e.target.value
  281. localStorage.setItem('theme', chosenColorScheme)
  282. toggleTheme(chosenColorScheme)
  283. })
  284. const selectedTheme = localStorage.getItem('theme')
  285. if (selectedTheme && selectedTheme !== 'undefined') {
  286. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  287. }
  288. }
  289. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  290. window.addEventListener('load', () => {
  291. let hasDarkRules = false
  292. for (const styleSheet of Array.from(document.styleSheets)) {
  293. let mediaRules = []
  294. for (const cssRule of styleSheet.cssRules) {
  295. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  296. continue
  297. }
  298. // WARNING: Safari does not have/supports `conditionText`.
  299. if (cssRule.conditionText) {
  300. if (cssRule.conditionText !== prefersColorSchemeDark) {
  301. continue
  302. }
  303. } else {
  304. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  305. continue
  306. }
  307. }
  308. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  309. }
  310. // WARNING: do not try to insert a Rule to a styleSheet you are
  311. // currently iterating on, otherwise the browser will be stuck
  312. // in a infinite loop…
  313. for (const mediaRule of mediaRules) {
  314. styleSheet.insertRule(mediaRule.cssText)
  315. hasDarkRules = true
  316. }
  317. }
  318. if (hasDarkRules) {
  319. loadThemeForm('#theme-selector')
  320. }
  321. })
  322. </script>
  323. </body>
  324. </html>