Single Attik order creates two Spectora orders

Objective

  • Ensure one online Attik booking produces exactly one Spectora order, with that Spectora job id stored on the Attik inspection (_spectoraJobId).
  • Prevent orphan Spectora orders (API-created jobs in Spectora that no Attik work order references), which break cancel/resync workflows and confuse coordinators.

Background

  • Reported on work order 1008592205: a single Attik order exists, but two Spectora orders were created; both show creator "Attik API" in Spectora, and only one is linked on the Attik side.
  • The affected job was booked through the public online scheduler (customer flow), not the internal scheduler’s Attik-vs-Spectora picker.
  • For companies on Attik standalone (or beta-online-scheduler-attik), the online UI calls inspection/book-job only—it does not call spectora/create-job on the same booking. Spectora jobs for those bookings are created by barebones sync after the Attik inspection is saved.
  • In Spectora, "Attik API" is consistent with jobs created via the API key integration (barebones POST inspections and full createSpectoraJob both use that path). Online Attik bookings that sync to Spectora use barebones sync with scheduled_by: attik-standalone on the Spectora payload.
  • Suspected failure mode: two overlapping barebones "create" runs both execute before _spectoraJobId is persisted—e.g. async sync on inspection insert while a follow-up inspection update (or a second sync trigger) still sees no linked id. createInspection performs a second save to attach events immediately after the first save; the change stream also fires barebones sync on later updates when status, charges, datetime, inspectors, or address change.
  • Slack thread: attik-talk discussion.

Scope

Frontend (online scheduler)

  • Public booking is implemented in attik-frontend/src/app/scheduler/summary/BookingJobLoader.tsx: when company.attikStandalone or beta-online-scheduler-attik is enabled, it posts to inspection/book-job with scheduledLocation: 'online' (not spectora/create-job).
  • hasBookedRef guards against double-submit in the loader; if duplicate Spectora jobs appear, investigation should include server-side duplicate creates, not only UI double-click.

Backend (booking)

  • POST /inspection/book-job in attik-backend/src/routes/inspection.ts calls createInspection in src/util/functions/inspection/createInspection.ts, which sets jobCreationType: 'attik' and scheduledLocation: 'online' (default when not internal).
  • Confirmed vs unconfirmed on create follows company schedule settings (createBookedJobsAsConfirmed); that affects whether later confirm updates also qualify for barebones sync.
  • After insert (and on qualifying updates), attik-backend/src/events/streamHandlers/inspectionStream.ts invokes syncBarebonesSpectoraJob from src/util/functions/spectora/syncBarebonesSpectoraJob.ts for jobCreationType === 'attik'.
  • Barebones sync creates via Spectora POST inspections when _spectoraJobId is missing, then updates when present. There is a late re-read for _spectoraJobId before create, but no distributed lock—concurrent runs can still double-create; only one id is typically saved on Attik.
  • Spectora webhooks in src/routes/webhooks/spectora/syncInspection.ts skip upsert when scheduled_by === 'attik-standalone' or when an Attik inspection already owns the Spectora job id—so the duplicate is unlikely to be webhook-created Attik rows; focus on duplicate API creates.
  • Full Spectora-first booking (src/routes/spectora.tscreateSpectoraJob) is out of scope for this repro unless investigation shows the company was not on standalone at book time.

Investigation (decision needed on root cause)

  • On inspection 1008592205: compare _spectoraJobId to both Spectora job ids; review AutomationEventHistory / logs for [SpectoraBarebonesSync] create vs create_success (timing, count).
  • Confirm company flags at book time (attikStandalone, scheduler feature flags) and inspection fields (jobCreationType, scheduledLocation, initial status).
  • Decision needed: idempotency strategy (per-inspection lock, atomic claim before POST, or stricter queue dedupe) and whether orphan Spectora jobs need operational cleanup tooling.

References

Please authenticate to join the conversation.

Upvoters
Status

Planned

Board
🏠

Main App

Date

13 days ago

Author

Linear

Subscribe to post

Get notified by email when there are changes.