You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
StackRecordAdapter and StackBlobAdapter both now carry optional capability methods that a caller checks for at runtime and falls back gracefully when absent:
Both are legitimately optional — adapter-api can implement neither today, since the wire protocol has no transactional-delete endpoint and no GET /attachments listing endpoint — so making them required would force a fake/non-atomic implementation behind a name that claims otherwise. Keeping them optional was the right call (raised and confirmed during #64's review).
But nothing surfaces their existence to someone writing a new adapter:
No IDE nudge. Optional interface members show up in autocomplete once you start typing the name, but most editors' "implement interface" quick-fix only inserts required members. Nothing prompts an implementor to notice the optional ones exist.
No spec checklist. The two methods are each documented in prose, in the section of §Attachments/§Adapters relevant to what they're for — not in one place an adapter author would think to check before considering their implementation done.
No runtime signal. Unlike AdapterCapabilities (fullTextSearch, contentFieldQuery, sortableFields — a required field every adapter must populate), these two are bare optional methods. Silence ("didn't implement it") is indistinguishable from "forgot it exists."
Point 3 is the sharper observation: this codebase already has a stronger pattern for exactly this problem, and these two capabilities don't use it. AdapterCapabilities being required is itself a forcing function — extending it is a compile error for every existing adapter until someone consciously decides true/false, and it's introspectable at runtime via stack.features. A bare foo?(): T on an interface has neither property: nothing breaks when it's missing, and nothing is queryable to check whether an adapter author considered it.
Non-goals
Not proposing these two become required. See above — adapter-api genuinely can't offer either honestly today.
Not proposing folding them into AdapterCapabilities as booleans. A flag and a method can disagree ({ atomicAttachmentDelete: true } with the method actually absent, or vice versa) in a way a single optional-method-presence check can't. The call sites (Stack.deleteAttachment(), Stack.collectAttachmentGarbage()) already check the method itself, which is the one place that can't lie.
Open question
Two directions worth weighing, not mutually exclusive:
Documentation fix. A short "Implementing your own adapter" section in spec's §Adapters listing every optional capability in one place — name, purpose, what happens when absent, which shipped adapters implement it. Cheap, immediately closes the "no checklist" gap, does nothing for the IDE-nudge gap.
A discoverable marker without a boolean-flag's lying problem — e.g. a lint rule or a documented convention (a comment block, a naming convention) that groups all StackRecordAdapter/StackBlobAdapter optional members so a grep/doc-generation pass can enumerate them mechanically, rather than an author having to already know to look. Bigger investment for a project whose adapter-authoring audience is currently small (two shipped record adapters, one blob adapter, one HTTP adapter) — probably not worth it until there's evidence of third-party adapters actually being written.
spec.md §Adapters: "Implementing your own adapter" checklist section enumerating deleteUnreferencedAttachmentRecords, listFiles, and any future optional capability, with purpose + fallback behavior + which shipped adapters implement each
Revisit whether new optional capabilities should default to being listed there as part of their own PR, so the checklist doesn't drift out of sync the way the prose mentions already have (each capability documented only where it's used, not where someone building an adapter would look)
Refs #64 (introduced the listFiles() capability and the pattern discussion), #46/#50 (established deleteUnreferencedAttachmentRecords? as the precedent this mirrors).
Problem
StackRecordAdapterandStackBlobAdapterboth now carry optional capability methods that a caller checks for at runtime and falls back gracefully when absent:StackRecordAdapter.deleteUnreferencedAttachmentRecords?(fileId, metadataTypeId)— atomic reference-check-then-delete, closing the raceStack.deleteAttachment()'s non-atomic fallback can't (spec §Attachments).StackBlobAdapter.listFiles?()— blob enumeration, lettingStack.collectAttachmentGarbage()(Orphaned blob GC: deleting the last referencing record leaves bytes on disk forever #64) find bare-bytes orphans that have no_attachment@1record at all.Both are legitimately optional —
adapter-apican implement neither today, since the wire protocol has no transactional-delete endpoint and noGET /attachmentslisting endpoint — so making them required would force a fake/non-atomic implementation behind a name that claims otherwise. Keeping them optional was the right call (raised and confirmed during #64's review).But nothing surfaces their existence to someone writing a new adapter:
AdapterCapabilities(fullTextSearch,contentFieldQuery,sortableFields— a required field every adapter must populate), these two are bare optional methods. Silence ("didn't implement it") is indistinguishable from "forgot it exists."Point 3 is the sharper observation: this codebase already has a stronger pattern for exactly this problem, and these two capabilities don't use it.
AdapterCapabilitiesbeing required is itself a forcing function — extending it is a compile error for every existing adapter until someone consciously decides true/false, and it's introspectable at runtime viastack.features. A barefoo?(): Ton an interface has neither property: nothing breaks when it's missing, and nothing is queryable to check whether an adapter author considered it.Non-goals
adapter-apigenuinely can't offer either honestly today.AdapterCapabilitiesas booleans. A flag and a method can disagree ({ atomicAttachmentDelete: true }with the method actually absent, or vice versa) in a way a single optional-method-presence check can't. The call sites (Stack.deleteAttachment(),Stack.collectAttachmentGarbage()) already check the method itself, which is the one place that can't lie.Open question
Two directions worth weighing, not mutually exclusive:
StackRecordAdapter/StackBlobAdapteroptional members so agrep/doc-generation pass can enumerate them mechanically, rather than an author having to already know to look. Bigger investment for a project whose adapter-authoring audience is currently small (two shipped record adapters, one blob adapter, one HTTP adapter) — probably not worth it until there's evidence of third-party adapters actually being written.Leaning toward (1) now, revisit (2) if/when external adapter implementations show up.
Work items
deleteUnreferencedAttachmentRecords,listFiles, and any future optional capability, with purpose + fallback behavior + which shipped adapters implement eachRefs #64 (introduced the
listFiles()capability and the pattern discussion), #46/#50 (establisheddeleteUnreferencedAttachmentRecords?as the precedent this mirrors).