Repository navigation
Conversation
holgpar
commented
Oct 15, 2026
- docs: explain event handling
- docs: fix referenced class names
- docs: more information on draft handling
- docs: more improvements on draft activation
- docs: improvements and rewrites on malware scanning
some classes refered to in the document got renamed
SummaryThe following content is AI-generated and provides a summary of the pull request: Improve Attachment Design DocumentationDocumentation📚 Clarifies the attachment feature architecture and runtime behavior, with expanded guidance for CAP event mapping, draft activation, storage backends, multi-tenancy, and malware scanning. Changes
Images and Links
PR Bot InformationVersion:
|
There was a problem hiding this comment.
The document is substantially clearer, but several references and lifecycle descriptions needed correction to avoid broken navigation and misleading extension guidance. Inline comments include targeted fixes.
PR Bot Information
Version: 1.33.5
- Correlation ID:
f8eecca0-c8a3-11f1-87cc-bb99223b8db1 - Agent Instructions:
- File Content Strategy: Full file content
- LLM:
gpt-5.6-sol - Event Trigger:
pull_request.opened
| After the handler has checked if an attachment entity is contained in the request, | ||
| the handler calls the `ModifyAttachmentEventFactory` implementation. | ||
| The implementation of this interface, `DefaultModifyAttachmentEventFactory`, checks | ||
| The implementation of this interface, `ModifyAttachmentEventFactory`, checks |
There was a problem hiding this comment.
Clarity: ModifyAttachmentEventFactory is a concrete class, not an implementation of an interface, so this description gives readers the wrong type hierarchy. Instead, describe the factory directly.
| The implementation of this interface, `ModifyAttachmentEventFactory`, checks | |
| The `ModifyAttachmentEventFactory` checks |
Double-check suggestion before committing. Edit this comment for amendments.
Please provide feedback on the review comment by checking the appropriate box:
- 🌟 Awesome comment, a human might have missed that.
- ✅ Helpful comment
- 🤷 Neutral
- ❌ This comment is not helpful
| | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| | `CreateAttachmentEvent` | Emits the `CREATE_ATTACHMENT` event on the `AttachmentService` | | ||
| | `DoNothingAttachmentEvent` | Used when the attachment entity is included in the request but nothing needs to be done, e.g. a field is updated which is not the `content` or `contentId` field | | ||
| | `MarkAsDeletedAttachmentEvent` | Emits the `MARK_AS_DELETED` event on the `AttachmentService`; skipped during `DRAFT_PATCH` events from the `DraftService` — in that case the mark as deleted is triggered when the draft is activated | |
There was a problem hiding this comment.
Logic Error: This names the wrong service event and incorrectly says deferred deletion occurs on draft activation; the service event is MARK_ATTACHMENT_AS_DELETED, and the draft-patch content is cleaned up on draft cancellation by DraftCancelAttachmentsHandler. This could mislead plugin implementers about which event to handle and when deletion occurs.
| | `MarkAsDeletedAttachmentEvent` | Emits the `MARK_AS_DELETED` event on the `AttachmentService`; skipped during `DRAFT_PATCH` events from the `DraftService` — in that case the mark as deleted is triggered when the draft is activated | | |
| | `MarkAsDeletedAttachmentEvent` | Emits the `MARK_ATTACHMENT_AS_DELETED` event on the `AttachmentService`; skipped during `DRAFT_PATCH` events from the `DraftService` — if the draft is cancelled, `DraftCancelAttachmentsHandler` deletes newly uploaded content that is not referenced by the active entity | |
Double-check suggestion before committing. Edit this comment for amendments.
Thank you for submitting your feedback: ✅ Helpful comment.
|
|
||
| For the create event a listener is registered for the end of the transaction to scan the content | ||
| of the attachment for malware. | ||
| For an external storage plugin, `isInternalStored` is left `false`, which |
There was a problem hiding this comment.
Clarity: External storage handlers explicitly set isInternalStored to false; saying it is “left” false obscures the extension contract that custom handlers must follow. Instead, state that the plugin sets the flag.
| For an external storage plugin, `isInternalStored` is left `false`, which | |
| For an external storage plugin, `isInternalStored` is set to `false`, which |
Double-check suggestion before committing. Edit this comment for amendments.
Please provide feedback on the review comment by checking the appropriate box:
- 🌟 Awesome comment, a human might have missed that.
- ✅ Helpful comment
- 🤷 Neutral
- ❌ This comment is not helpful
| in file `com.sap.cds.services.runtime.CdsRuntimeConfiguration` to make it visible for the CAP Java runtime. | ||
|
|
||
| ### Handler | ||
| ### Handlers |
There was a problem hiding this comment.
Bug: Renaming this heading changes its generated anchor to #handlers, but the table of contents still links to #handler, leaving a broken navigation link. Consider updating the TOC entry to [Handlers](#handlers) as part of this rename.
Thank you for submitting your feedback: ✅ Helpful comment.
tomk8r
left a comment
There was a problem hiding this comment.
Much clearer and up to date.
Just some smaller suggestions - you can take or leave them.
| | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| | `CreateAttachmentEvent` | Emits the `CREATE_ATTACHMENT` event on the `AttachmentService` | | ||
| | `DoNothingAttachmentEvent` | Used when the attachment entity is included in the request but nothing needs to be done, e.g. a field is updated which is not the `content` or `contentId` field | | ||
| | `MarkAsDeletedAttachmentEvent` | Emits the `MARK_AS_DELETED` event on the `AttachmentService`; skipped during `DRAFT_PATCH` events from the `DraftService` — in that case the mark as deleted is triggered when the draft is activated | |
There was a problem hiding this comment.
We should rather use the bot suggestion. Most accurate (with CLAUDE support) would be:
| MarkAsDeletedAttachmentEvent | Emits the MARK_ATTACHMENT_AS_DELETED event on the AttachmentService; skipped during DRAFT_PATCH events from the DraftService — the external delete is deferred until the draft is either cancelled (DraftCancelAttachmentsHandler) or activated (UpdateAttachmentsHandler.deleteRemovedAttachments).
| getQualifiedName(). | ||
|
|
||
| endsWith("_drafts"); | ||
| DraftUtils.getActiveEntity(entity); // returns the active sibling |
There was a problem hiding this comment.
| DraftUtils.getActiveEntity(entity); // returns the active sibling | |
| DraftUtils.getActiveEntity(entity); // returns the active entity, navigating to the sibling if the input is a draft entity |
|
|
||
| endsWith("_drafts"); | ||
| DraftUtils.getActiveEntity(entity); // returns the active sibling | ||
| DraftUtils.getDraftEntity(entity); // returns the draft sibling |
There was a problem hiding this comment.
| DraftUtils.getDraftEntity(entity); // returns the draft sibling | |
| DraftUtils.getDraftEntity(entity); // returns the draft entity, navigating to the sibling if the input is an active entity |
| Tenant information does not need to be passed explicitly when emitting events | ||
| on the `AttachmentService` — CAP propagates it automatically via the | ||
| `RequestContext`, which is available on the current thread. | ||
|
|
There was a problem hiding this comment.
| For asynchronous operations (e.g. the malware scan), a `RequestContextRunner` is captured on the parent thread and replayed on the child thread to restore the tenant context. |