Import repeater contacts: preview loads but the import is never sent, so contacts vanish on refresh #22

Open
opened 2026-10-27 15:24:54 +01:00 by adam · 1 comment
Owner

Summary

Console v0.9.365. "Import repeater contacts" ("Seed with contacts from the repeater's adverts. Results are ordered by most recent first.") fetches the preview and never performs the import. The contacts appear in the UI, and are gone on the next page load, because nothing was ever written.

Evidence

I instrumented the repeater (a before_handler CherryPy tool logging every request, plus a hook on the companion frame server's command dispatch) and clicked the button. The complete set of requests it makes:

GET /api/adverts_by_contact_type?contact_type=Room+Server
GET /api/adverts_by_contact_type?contact_type=Chat+Node
GET /api/adverts_by_contact_type?contact_type=Repeater

Three GETs, then nothing. Specifically, over several attempts:

  • no POST /api/companion/import_repeater_contacts — the endpoint that implements this feature, whose docstring matches the button's own description ("Import repeater adverts into this companion's contact store (one-time seed). Results are sorted by last_seen DESC.")
  • no POST/PUT/PATCH/DELETE of any kind
  • no CMD_ADD_UPDATE_CONTACT / CMD_IMPORT_CONTACT / CMD_REMOVE_CONTACT over the companion frame transport (instrumented at the dispatcher; zero received)
  • no change to companion_contacts in SQLite — the target companion stayed at 114 rows across every attempt

The UI displayed all 285 adverts each time, so the preview itself works; only the write is missing.

Expected

After the preview, POST the selection to /api/companion/import_repeater_contacts with {companion_name, contact_types?, hours?, limit?} and report imported / removed from the response.

Note for whoever picks this up

That endpoint has its own bug which will bite as soon as the Console starts calling it: it compares the API's type names (repeater, companion, room_server, sensor) against the display names stored in adverts.contact_type (Repeater, Chat Node, Room Server, Sensor), so any request carrying contact_types imports zero rows. Reported and fixed at openhop-dev/openhop_repeater#435 / #436. If the Console sends type filters — and its UI implies it will — both fixes are needed for this feature to work.

Environment

Console v0.9.365, openHop Repeater 0.1.dev1191, openhop_core 1.1.3.dev25, Raspberry Pi 4, Python 3.13.5.

### Summary **Console v0.9.365.** "Import repeater contacts" ("Seed <companion> with contacts from the repeater's adverts. Results are ordered by most recent first.") fetches the preview and never performs the import. The contacts appear in the UI, and are gone on the next page load, because nothing was ever written. ### Evidence I instrumented the repeater (a `before_handler` CherryPy tool logging every request, plus a hook on the companion frame server's command dispatch) and clicked the button. The complete set of requests it makes: ``` GET /api/adverts_by_contact_type?contact_type=Room+Server GET /api/adverts_by_contact_type?contact_type=Chat+Node GET /api/adverts_by_contact_type?contact_type=Repeater ``` Three GETs, then nothing. Specifically, over several attempts: - **no** `POST /api/companion/import_repeater_contacts` — the endpoint that implements this feature, whose docstring matches the button's own description ("Import repeater adverts into this companion's contact store (one-time seed). Results are sorted by last_seen DESC.") - **no** POST/PUT/PATCH/DELETE of any kind - **no** `CMD_ADD_UPDATE_CONTACT` / `CMD_IMPORT_CONTACT` / `CMD_REMOVE_CONTACT` over the companion frame transport (instrumented at the dispatcher; zero received) - **no** change to `companion_contacts` in SQLite — the target companion stayed at 114 rows across every attempt The UI displayed all 285 adverts each time, so the preview itself works; only the write is missing. ### Expected After the preview, POST the selection to `/api/companion/import_repeater_contacts` with `{companion_name, contact_types?, hours?, limit?}` and report `imported` / `removed` from the response. ### Note for whoever picks this up That endpoint has its own bug which will bite as soon as the Console starts calling it: it compares the API's type names (`repeater`, `companion`, `room_server`, `sensor`) against the display names stored in `adverts.contact_type` (`Repeater`, `Chat Node`, `Room Server`, `Sensor`), so **any** request carrying `contact_types` imports zero rows. Reported and fixed at openhop-dev/openhop_repeater#435 / #436. If the Console sends type filters — and its UI implies it will — both fixes are needed for this feature to work. ### Environment Console v0.9.365, openHop Repeater 0.1.dev1191, openhop_core 1.1.3.dev25, Raspberry Pi 4, Python 3.13.5. <!-- github-sync-id:5338358748 -->
Author
Owner

Still present on 0.9.368.

Re-tested after upgrading 0.9.365 → 0.9.368 (hard-refreshed to clear the cached bundle). Same result: the preview renders the full advert list, and the target companion's companion_contacts row count is unchanged — measured before and after with

SELECT companion_hash, COUNT(*), MAX(updated_at) FROM companion_contacts GROUP BY 1;

All four companions: +0. Most recent write predates the click.

Worth recording because 0.9.366 reworked the companion/messages page including the roster's Import key, so it was a reasonable candidate to have fixed this incidentally. It did not — the behaviour is identical across 0.9.365 and 0.9.368, which suggests the missing call is not in the part that was rewritten.

The repeater side is healthy and current in this test (openhop_core 1.1.3.dev25, openhop_repeater 0.1.dev1192, both at upstream dev HEAD), and POST /api/companion/import_repeater_contacts works correctly when called directly — a manual call against the same companion returned {"success": true, "data": {"imported": 285, "removed": 0}} and the rows persisted. So the endpoint and the database path are fine; only the Console's request is missing.

Still present on **0.9.368**. Re-tested after upgrading 0.9.365 → 0.9.368 (hard-refreshed to clear the cached bundle). Same result: the preview renders the full advert list, and the target companion's `companion_contacts` row count is unchanged — measured before and after with ```sql SELECT companion_hash, COUNT(*), MAX(updated_at) FROM companion_contacts GROUP BY 1; ``` All four companions: **+0**. Most recent write predates the click. Worth recording because 0.9.366 reworked the companion/messages page including the roster's Import key, so it was a reasonable candidate to have fixed this incidentally. It did not — the behaviour is identical across 0.9.365 and 0.9.368, which suggests the missing call is not in the part that was rewritten. The repeater side is healthy and current in this test (openhop_core `1.1.3.dev25`, openhop_repeater `0.1.dev1192`, both at upstream `dev` HEAD), and `POST /api/companion/import_repeater_contacts` works correctly when called directly — a manual call against the same companion returned `{"success": true, "data": {"imported": 285, "removed": 0}}` and the rows persisted. So the endpoint and the database path are fine; only the Console's request is missing. <!-- github-comment-id:5530002073 -->
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: adam/pymc_console-dist#22