ByteCode.NewsSubmit
Use quotes for an exact word.

Subscribe

RSSPodcast
Log in

Chat Logs

  1. * skillbot quit (Remote host closed the connection)
  2. * skillnews quit (Remote host closed the connection)
  3. * skillbot joined #primate
  4. * skillnews joined #primate
  5. bot[ByteCode.News] Andrew Lombardi: Unit Tests are Not the Enemy - https://bytecode.news/posts/2026/10/andrew-lombardi-unit-tests-are-not-the-enemy
  6. bot[ByteCode.News] Arcana Reads Everything, and Then Some - https://bytecode.news/posts/2026/10/arcana-reads-everything-and-then-some
  7. bluedreamreal: good take by Lombardi there
  8. bluealso, what kind of idiot just deletes unit tests...
  9. * lioloc joined #primate
  10. liolocblue: Hey blue ! Just to remember, right now there is no package to help with caching in the browser right? Like for instance if you receive props and you wanted to cache those props for the next time the user visits the page, would there be a way to do this?
  11. liolocCaching is a topic that's always been a bit tough for me to understand (backend vs browser)
  12. liolocI usually just use packages like tanstack/query that handles the caching mechanisms for me for the browser, and since now I instead typically make the queries in the route, these are backend fetches right? So I can't cache those unless I use redis or something like that right?
  13. liolocI'm trying to understand what would be the right mechanisms to use caching in Primate for both use cases:
  14. lioloc1. You're doing a fetch in a route
  15. lioloc2. You receive props and maybe you want to cache those (or do you need to instead use a query library on the frontend instead and do the call here instead?)
  16. bluehi lioloc
  17. bluecan you describe the use case so it's easier to understand? when do you want to cache props? And if you're fetching in a route, that's already on the server, there you'd probably use a caching server like redis. There are plans for a @primate/kv package: https://repopack.com/project/primate/tasks/10
  18. bluebut I think it'd be easier for me to offer you paths forward if I understand your actual use case
  19. dreamrealblue: revamped the primate build's topbar
  20. dreamrealit was getting gross
  21. bluegood good
  22. bluedreamreal: release artifacts landed today in repopack; it turned out a bit more than I'd bargained for, but the model is strong, I think; it has products, channels, and releases; releases draw from job runs; and can be promoted to channels. Channels carry access levels (PUBLIC or PROJECT). products are, well, a single publishable entity
  23. liolocblue: Let's say in a route I fetch: Races and pass them as a prop to Index.vue, races is an array of objects and maybe it can contain 100 results
  24. dreamrealNoice!
  25. blueso the `rp` cli is a "product"; it has channels (stable, unstable); and there are releases, either unassigned to any channel (in which case they are project-private), or assigned to a channel
  26. liolocblue: This is small enough that it isn't an issue without caching I would assume. But let's say there are like 10000 races and I want the experience of the application to feel extremely rapid when I'm moving from page to page, so that I can come back to a previous tab
  27. bluelioloc: so you load 10k races at once and want to keep it in the browser tab's memory; and those 10k races never change?
  28. liolocLet's say we want to control when they change, like maybe we want to refetch only after 5 minutes
  29. liolocso they won't change for 5 minutes
  30. bluehow would you feel about `response.page(props, { cache: { ttl: 60 /* seconds */ } })`?
  31. liolocI'm not sure if keeping it in the browser's memory is the best answer btw, I'm just trying to get the fastest experience for a user
  32. blueand same for response.view
  33. liolocthat would be neat
  34. bluethat would be transparent for you; the primate fetch-client would serialise the path, and cache on the serialised key
  35. bluethe route itself would likely send something like `Primate-Cache: max-age=60` along the response
  36. blueas a header
  37. liolocthis is for browser caching or server side caching btw?
  38. bluebrowser caching
  39. blueprops caching
  40. blueserver side caching is the easier problem there because you can write a small cache yourself fairly easily. @primate/kv could help there but it's relatively trivial to do it yourself first. the client part isn't
  41. liolochave you used something like tanstack/query? They also have the ability to invalidate a cache on the client, for optimistic updates, it can quickly can get confusing imo
  42. blueI haven't, but I was going to say that what I just purposed is a streamlined version of tanstack/query, where you don't need to manage the caching keys yourself
  43. bluefrom the documentation of tanstack/query, it appears terribly overengineered to me
  44. liolocbut what if you wanted to invalidate the cache once a user presses a button for instance?
  45. liolocwould be neat to be able to do that too
  46. bluethen we should expose something on `primate/navigate`, probably
  47. bluehttps://primate-master.repopack.app/blog/primate-043#navigation-that-says-what-it-does
  48. nevetPrimate — Primate 0.43: diamond migrations, deferred navigation and direct SQL
  49. bluemaybe navigate.cache.clear()
  50. liolocyeah would be neat
  51. liolocI guess it's also because something like tanstack/query is used client side, not server side
  52. liolocso you'll have multiple different query calls client side, each with their own cache key
  53. liolocIn primate's case, if you do the fetch in the route directly, wouldn't that mean that "Time to first paint" would be slower than in an app using tanstack/query to load things after?
  54. liolocI mean naturally it would right? Cause you're fetching before serving the page. I'm thinking like the case of an app's dashboard for a logged in user for instance.
  55. blueThat's a real distinction, however primate 0.43 will have response.defer
  56. bluewhich will allow you to use suspence boundaries or awaits inside clients
  57. bluesuspense*
  58. bluehttps://primate-master.repopack.app/blog/primate-043#stream-page-data-during-navigation
  59. nevetPrimate — Primate 0.43: diamond migrations, deferred navigation and direct SQL
  60. liolocoh wow
  61. liolocvery neat
  62. liolocif we introduce caching then maybe with defer you should also be able to invalidate a specific one?
  63. bluea specific prop?
  64. liolocyeah
  65. lioloccause if you have many props, perhaps you don't want everything to reload if you invalidate the cache
  66. liolocI mean reload every prop
  67. liolocwhat do you think?
  68. bluehm, selective browser updates can be hard
  69. blueI mean, we could potentially support navigate.cache.clear(key). but the mechanism behind it could turn out complicated
  70. blueif we have `response.page(props, { cache: { ttl: 60 /* seconds */ } })`, the browser would simply not call the route for 60 seconds
  71. bluebut if we start breaking it down to props, that's a bit harder: the browser needs to call the route for *some* props, and the route suddenly might need to know not to care about some props. the complexity is higher
  72. liolocyeah for sure
  73. bluelioloc: this is complex stuff. however, this could make sense:
  74. blueactivity: response.defer(() => loadActivity(), { ttl: 600 })
  75. bluethe lazy form means we can save actual work on the server, *for the particular client*
  76. bluewithout the lazy form, the gains aren't significant
  77. liolocin essence what does that lazy call mean? as opposed to without the lazy call
  78. bluewell, imagine we browse back to the page within the cache's lifetime. since we have a mixture between cached and non-cached prompts, primate has to issue a server request
  79. blueso it issues it with something like "I want this prop, but this prop is already cached and I don't need it)
  80. bluehowever, something like on this server:
  81. blueactivity: response.defer(loadActivity(project)),
  82. bluewill always do the work. loadActivity is essentially a promise-returning function, so the promise will return anyway on the server, and its output would be discard
  83. bluesomething like:
  84. blueresponse.defer(() => loadActivity(project), { ttl: 600 })
  85. bluecan be prevented from running at all if the cache boundary holds
  86. blues/prompts/props/
  87. bluethe question whether page-level caching (so an option on response.page) is enough or whether you want the prop granularity
  88. blueI'm not sure having both mechanisms makes sense, that's a lot of different combinations needed to be accounted for
  89. blueif prop granularity is actually what you're looking for, then we should explore extending response.defer to accept a lazy function and a ttl
  90. blueif caching an entire page (=all its props) is what you're looking for, that's easier
  91. bluebut I'm a bit hesitant to do both
  92. bluefwiw, the non-lazy form could still make a revisit *feel faster*. since the server work isn't blocking. but it happens anyway, that's a bit of a waste; maybe it's insignificant; though if we're talking about getting 10k records from a db, it might be
  93. bluedreamreal: would you also benefit from a client cache?
  94. bluespecifically I think that if someone has loaded an article before, it might be useful to cache. but I don't know the exact model of how you serve articles. you serve the entire rendered html, no?
  95. liolocwhat if it wasn't a response.defer function but just a "browserCache(" function (name irrelevant)? That way you can just decide whatever you want cached, whether it is the entire html or a specific portion, like props
  96. liolocjust spitballing ideas
  97. dreamrealI mean... maybe, but it would rely on a lot of retention
  98. blueyeah, but "whatever you want" cache still implies someone has to bookkeep that cache, and that's the complex part
  99. bluea different approach, lioloc, is a offer a `primate/query` or so
  100. * skillbot quit (Remote host closed the connection)
  101. * skillnews quit (Read error: Connection reset by peer)
  102. * skillbot joined #primate
  103. * skillnews joined #primate
  104. bluehttps://dpaste.com/7NMKZMRM7
  105. bluebut I feel this is perhaps more relevant for BCN than what you just described
  106. dreamrealWell, it presumes retention, still
  107. bluelioloc: maybe you can create a small example and I can play around with it
  108. blueyes dreamreal, caching is widely also known as retention
  109. dreamrealstandard use on BCN is not a lot of interrelated post traffic, which annoys me but is reflected in traffic patterns
  110. bluethank you for stating the obvious :P
  111. dreamrealI'm not trying to state the obvious, I'm talking about whether that pattern makes sense for BCN, whose traffic patterns would NOT show a benefit as yet
  112. blueconst response = await posts.get({ path: { slug }, cache: { ttl: 300 },
  113. blue});
  114. dreamrealYou wanted me to look, I looked, damn it
  115. bluedreamreal: lioloc: what do we think about this?
  116. bluein one line: `const response = await posts.get({ path: { slug }, cache: { ttl: 300 }});`
  117. blueidk if any of those ideas seems coherent
  118. dreamrealsure
  119. dreamrealI don't have a problem with it at all, it just wouldn't affect BCN :D
  120. bluewell you know me, I'm loath to add things that are over-engineered, or complicated to understand or use
  121. dreamrealI don't think it's overengineered or difficult to understand
  122. dreamrealin fact I think its' really easy to understand
  123. bluewhich of the five options I offered?
  124. dreamrealThe one that seemed to make sense to me was https://dpaste.com/7NMKZMRM7
  125. blueoh
  126. * lioloc quit (Ping timeout: 245 seconds)
  127. bluedreamreal: flog is live and installable at https://flog.run
  128. nevetflog — predictable JavaScript package management
  129. blue(using repopack release primitives)
  130. blueI will also publish an sdk for releases at @repopack/release; do you need one for java/kotlin as well?
  131. dreamrealblue: what would primate's BCN build look like with flog?
  132. dreamrealshould have a "conversion from those other stupid package managers" section
  133. dreamrealjava's a much harder climb because of maven repositories
  134. bluedreamreal: well, flog is currently mostly for npm; but the commands aren't js specific. the question is what do you need / what do you expect the workflow to be; generally, flog works like this:
  135. blueflog add / remove: adds or removes a dependency
  136. blueflog upgrade: upgrades dependencies (interactively)
  137. blueflog lock: create a lockfile
  138. blueflog install: materialises a lockfile
  139. blueif those primitives are transferable to maven, then there is no reason flog wouldn't be able to manage maven projects / pom.xml projects
  140. blue(flog add/remove/upgrade also changes a lockfile)
  141. dreamrealmaven IS a lockfile, there're analogs but they're not esp applicable in the space
  142. bluedreamreal: just to be clear, you're looking to replace maven on the kotlin/java app, or pnpm on the primate-ui app, or both?
  143. dreamrealpnpm mainly, although it actually used npm itself unless you changed it
  144. blueoh ok, then it's different from what I thought
  145. blueflog should be able to replace pnpm/npm 1:1 and be much faster
  146. dreamreal*nod* if you want to, try it on ui-primate
  147. dreamrealgood real-world-ish project
  148. blueya