Repository navigation
feat(collectives-publish) inform publish service about archive ready - #2855
Conversation
|
I gonna review. only a meta thing in advance: Let us use our defined pattern for the PR naming: |
| public function create(int $collectiveId, array $pageIds, string $userId, ?string $title = null, ?string $slug = null): StaticSite { | ||
| $pageIds = $this->normalizePageIds($pageIds); | ||
| $collective = $this->getEditableCollective($collectiveId, $userId); | ||
| $this->generatorClient->assertConfigured(); |
There was a problem hiding this comment.
I think this is called more often than necessary. It is called explicitly here and on update and then in StaticSiteGeneratorClient:108 again on each build
There was a problem hiding this comment.
The calls are all making sense:
- StaticSiteService::create()
--> assures the correct configuration before build() - StaticSiteService::update()
--> same - also if not configured would set statsu to pending, and set status to failed on build() - we want an early fail - StaticSiteGeneratorClient::request()
--> assures that every request asserts the config - double check ist only read process and sored after first call.
| @@ -0,0 +1,16 @@ | |||
| <?php | |||
There was a problem hiding this comment.
probably there are reasons for wirting every excpetion to a seperate file and not all in StaticSiteGeneratorException.php ?!
There was a problem hiding this comment.
From what I understand, they're used to distinguish different error states and show separate error messages. Makes sense to me.
There was a problem hiding this comment.
Exactly - the idea was that the user could be informed if this is a temporary error and to retry later or if it is neccessary to contact an admin.
There was a problem hiding this comment.
sure. i just wodnered, wether they all can be in one file, because the yseem to be inhereted from one class, but never mind :)
| * | ||
| * Other app config keys are not declared, so strictness must stay IGNORE. | ||
| */ | ||
| class ConfigLexicon implements ILexicon { |
There was a problem hiding this comment.
Nice that you introduce a config lexicon. I'm not sure though if we can have one that only contains parts of the app config settings. I guess it should be comprehensive if we add it. I can look into opening a PR that adds a config lexicon to Collectives main branch already and then you can add the new settings into it with your PRs, what do you think?
There was a problem hiding this comment.
Super great - I wanted to ask you about that anyway.
It would have worked for now because of return Strictness::IGNORE;
And I introduced it because I needed it to automatically save the shared secret to the db as encrypted...
Perfect.
thx
7c64523 to
090efb9
Compare
dda822d to
0af8781
Compare
090efb9 to
6ac7363
Compare
- add static site generator settings and connection test - add public download endpoint to stream the archive to the external ssg service - notify static site generator when the provided archive is ready - regenerate OpenAPI specs (adds administration scope) Signed-off-by: Melpo <melpomene@posteo.net> Assisted-by: ClaudeCode:claude-opus-5-5
47c75f2 to
9ee2289
Compare
📝 Summary
Goal
The tar.gz archive has already been created and stored.
The goal is now to notify the Publish Service that the archive is ready for download (API call).
And to provide an API to download the archive.
Description
API of the ext. SSG Service:
POST /build
returns:
Limitations:
callback_status_urlcoming with the notification - this is part of another PR: feat(collectives-publish) static site update endpoint #2830 - Therefore the SSG does not accept the request and returns a502 Bad Gatewaythat results in an error message shown in the UI./healthto validate)Acceptance Criteria
🖼️ Screenshots
🚧 TODO
🏁 Checklist
npm run lint/npm run stylelint/composer run cs:check)🤖 AI (if applicable)
Mermaid BPMN Diagramm for the Publish Process in Collectives
flowchart TD %% ---------- Lane: User / Frontend ---------- subgraph FE["User / Frontend (CollectivePublishModal)"] start([Click 'Publish website']) feValid{Title and slug valid?} feDisabled([Button disabled]) fePages{At least one page selected?} feNoPages([Error toast: select at least one page]) post[POST /static-sites] feOk([Success toast 'Website publishing started', modal closes]) feWarn([Warning toast with message, modal stays open, input kept]) feErr([Error toast with message, modal stays open, input kept]) end %% ---------- Lane: Nextcloud backend ---------- subgraph NC["Nextcloud (StaticSiteController / StaticSiteService)"] perm{Collective found and user can edit?} conf{Publish service configured?} valid{Title, slug and pages valid?} insert[Insert static site, status pending] slugFree{Slug free?} collect[Collect files of the collective] size{Total size within static_site_max_size?} archive[Build tar.gz and store in appdata] archOk{Archive stored? paths valid, not empty} notify[POST /build to publish service] accepted{Response 2xx + enqueued?} temp{Not reachable, timeout or 5xx?} cleanup[Delete static site and archive] finish[Store title, page selection, status provided] stillThere{Static site still exists?} delArch[Delete archive] end %% ---------- Lane: Publish service ---------- subgraph SSG["External publish service"] enqueue[Enqueue build] download[GET archive with bearer token] end %% ---------- Lane: Archive download (async) ---------- subgraph DL["Nextcloud (StaticSiteArchiveController)"] blocked{More than 10 failed attempts in 30 min?} token{Bearer token valid?} exists{Static site and archive exist?} r429([429 Too Many Requests]) r401([401, attempt counted]) r404([404]) r200([200, tar.gz streamed]) end start --> feValid feValid -- no --> feDisabled feValid -- yes --> fePages fePages -- no --> feNoPages fePages -- yes --> post --> perm perm -- "no: 403 / 404" --> feWarn perm -- yes --> conf conf -- "no: 503 'not set up', logged" --> feErr conf -- yes --> valid valid -- "no: 400 / 404" --> feWarn valid -- yes --> insert --> slugFree slugFree -- "no: 400 'slug in use'" --> feWarn slugFree -- yes --> collect --> size size -- "no: 400, names 3 largest files" --> cleanup size -- yes --> archive --> archOk archOk -- "no: 400 path too long / no content, 500 storage error" --> cleanup archOk -- yes --> notify --> enqueue enqueue --> accepted accepted -- yes --> finish --> stillThere accepted -- no --> temp temp -- "yes: 503 'try again later'" --> cleanup temp -- "no: 502 'rejected', error logged" --> cleanup cleanup -- "4xx" --> feWarn cleanup -- "5xx" --> feErr stillThere -- yes --> feOk stillThere -- "no: 404" --> delArch --> feWarn enqueue -. "async, may start before status is provided" .-> download download --> blocked blocked -- yes --> r429 blocked -- no --> token token -- no --> r401 token -- yes --> exists exists -- no --> r404 exists -- yes --> r200