Files

8.0 KiB
Raw Permalink Blame History

Cross-references (FK между справочниками)

JSON Schema extension x-references объявляет, что значение поля должно ссылаться на active record в указанном словаре.

Синтаксис

{
  "type": "object",
  "properties": {
    "satelliteTypeCode": {
      "type": "string",
      "x-references": "satellite_type.code"
    }
  }
}

Format: "<dictionary_name>.<field_name>". Когда POST/PUT приходит, Ordinis делает lookup в satellite_type где data->>code == satelliteTypeCode. Если не найден / не активен / вне scope — 422 Validation Error.

Текущие FK в bundle cuod

Source Target Поле
spacecraft.satelliteTypeCode satellite_type code
spacecraft.statusCode spacecraft_status code
mission.spacecraftCodes (array) spacecraft businessKey
instrument.spacecraftCodes (array) spacecraft businessKey
instrument.supportedFormatCodes (array) data_format businessKey
instrument.supportedLevelCodes (array) processing_level businessKey

(Точное число и список могут меняться с bundle versions — см. Bundle cuod.)

Server-side validation

При POST/PUT ReferenceValidator проверяет каждое x-references поле:

Симптом Error code Описание
Referenced dictionary не существует x_references_dict_not_found Опечатка в schema.
Referenced record не найден / inactive x_references_target_not_found Bad value либо record закрыт.
Value не string (для v1) x_references_non_string v1 поддерживает только string refs.
Schema spec malformed x_references_malformed Bad schema.

Response:

{
  "errors": [
    {
      "path": "/satelliteTypeCode",
      "code": "x_references_target_not_found",
      "message": "Referenced record not found in 'satellite_type' for code='UNKNOWN-TYPE'"
    }
  ]
}

Scope hiding

Если referenced dictionary — INTERNAL/RESTRICTED, а consumer имеет только PUBLIC scope, ReferenceValidator возвращает тот же error (x_references_target_not_found) что и на real not-found. Ordinis не leak'ает existence of out-of-scope dictionary через differential errors.

Orphan references

Возможна ситуация когда referenced record закрывается, а referencing record остаётся:

1. spacecraft.RESURS-P-3 references satellite_type.EARTH-OPTICAL
2. Admin closes satellite_type.EARTH-OPTICAL  (record.closed event emitted)
3. spacecraft.RESURS-P-3 теперь имеет dangling FK

Ordinis периодически детектирует такие orphan'ы серверной стороной — данные не корректируются автоматически (может быть intentional state до update referencing записей), но Ordinis team получает уведомление и может coordinate fix с data stewards.

Consumer-side defensiveness:

  • При получении event record.closed для записи на которую ты ссылаешься — invalidate свой cache + либо fetch свежую версию referencing записи (если она тоже обновилась), либо handle dangling FK явно.

Cascade rules — roadmap (v2)

Сегодня закрытие источника НЕ closes referencing automatically. Это дoлжно явно делаться через bulk close либо individual updates.

В v2 планируется schema extension x-references-on-close:

{
  "satelliteTypeCode": {
    "type": "string",
    "x-references": "satellite_type.code",
    "x-references-on-close": "block"
  }
}

Опции:

  • block — закрытие источника невозможно пока есть active referencing (default).
  • warn — закрытие проходит, в response warning.
  • cascade — все referencing закрываются в той же транзакции, отдельные events emit'ятся per record.

Конкретный timeline и финальная семантика будут опубликованы перед deployment v2 — следи за анонсами от Ordinis team.

Lineage discovery — roadmap (v2)

Сегодня нет endpoint для "что depends on X". В v2 планируется:

  • GET /api/v1/dictionaries/{name}/dependents — словари которые ссылаются.
  • GET /api/v1/records/{dict}/{key}/dependents — конкретные записи.

Это позволит consumer'ам и UI узнавать связи без чтения всех schemas руками. Spec будет опубликован перед deployment v2.

Best practices

  1. Используй businessKey как target field для большинства FK. Это стабильный идентификатор. Альтернатива (code, name) работает но требует поддержки x-unique в target (иначе ambiguous matches).
  2. Не делай deeply nested refs — v1 поддерживает только top-level fields. Nested objects с x-references — пропустят validation.
  3. Array refs работают — если поле type: array, items: {type: string, x-references: ...}, каждый элемент валидируется. (Но в v1.2.1 это делается на каждый элемент отдельно — for large arrays медленно. Будет batch'нуто в v2.)
  4. Document FK в displayName"description": "FK на satellite_type через code" помогает при ревью schemas.

Связанные schema extensions

x-localized — мультиязычные поля

{ "type": "object", "x-localized": true }

См. read-endpoints.md ?lang= параметр.

x-section — bucketing полей в admin-UI form

Hint для admin-UI: в какую визуальную секцию формы (identity, references, description, dates, geometry, physical, extra, либо custom string) сгруппировать поле.

{
  "type": "number",
  "x-section": "orbital_geometry"
}

Если x-section не задан, admin-UI применяет эвристику:

  • x-referencesreferences
  • x-localizeddescription
  • format=date|date-timedates
  • key matches /^(geo|geom|wkt|lon|lng|lat|altitude|coord)/geometry
  • requiredidentity
  • else → extra

Predefined IDs получают i18n labels (Связи / Описание / Даты / Геометрия / Физические параметры / Идентификация / Дополнительно). Custom IDs humanize'ятся: orbital_geometryOrbital Geometry.

Только UI hint — backend не validate'ит и не reject'ит unknown values.

x-id-source — авто-derive businessKey

{ "x-id-source": "code" }

При CREATE businessKey берётся из data.code automatically (UI скрывает поле). См. ReferenceValidator.

x-unique — уникальность поля в dict'е

{ "type": "string", "x-unique": true }

Backend enforce'ит при CREATE/UPDATE. Используется для code полей в target dicts которые ссылаются по x-references.

Дальше

  • Bundle cuod — список текущих FK в проде
  • События — учитывай cascade closure при инвалидации
  • Schema workflow — как менять schema через approval flow