Skip to content

Invenqor v0.2.31

Choose a tag to compare

@hkjang hkjang released this 10 Sep 08:57
· 9 commits to main since this release

Invenqor Server·Agent v0.2.31 릴리즈 노트

릴리즈 일자: 2026-09-10
호환 Agent: v0.2.31 (Linux·Windows)

이번 릴리즈는 결함 하나를 고칩니다. 자리는 **Query DSL 실행
(POST /api/v1/query/execute)**이고, 지난 릴리즈가 붙인 표시의 뒷일입니다.
v0.2.29는 결과가 잘렸다는 사실을 truncated로 알리게 했지만, 잘린 나머지를
가져올 방법은 여전히 없었습니다.
이제 나머지를 가져올 수 있습니다.

1. 한도를 넘는 질의 결과에는 두 번째 페이지가 없었습니다

Query DSL 실행은 한 번에 기본 100건, 최대 500건까지 읽습니다. 그런데 이
엔드포인트에는 offset이 없었습니다. 조건에 맞는 자산이 한도보다 많으면
truncatedtrue로 돌아올 뿐, 그다음 자산을 요청할 방법이 없었습니다.

남은 방법은 조건을 잘게 쪼개는 것뿐이었습니다. 각 변형이 한도 아래로 들어올
때까지 표현식을 좁히고, 그 조각들을 호출한 쪽에서 다시 이어 붙여야 했습니다.
1,200대가 조용해진 인벤토리에서 last_seen_at < "now - 720h"limit 500으로
실행하면 500건이 돌아왔고, 나머지 700대로 가는 길이 없었습니다.
엔드포인트는 API key로도 열리므로, 그렇게 쪼개는 쪽은 대개 사람이 보는 콘솔이
아니라 스크립트였습니다.

이제 실행 입력이 /api/v1/assets와 같은 offset을 받습니다.

  • 끝까지 순회할 수 있습니다. 응답이 offset·has_more·next_offset
    돌려주므로, has_moretrue인 동안 직전 응답의 next_offset을 그대로
    offset에 넣어 다시 실행하면 전체 결과를 남김없이 읽습니다.
  • total은 조건에 맞는 전체 수입니다. 페이지 인자가 붙기 전의 같은
    표현식으로 COUNT(*)를 한 번 더 물어, 응답이 건네준 수가 아니라 맞은 수
    말합니다. query.execute 감사 로그에도 totaloffset이 함께 남습니다.
  • truncated는 그대로입니다. 뜻도 값도 has_more와 같으므로, offset이 없던
    시절에 작성된 호출자는 고치지 않아도 그대로 동작합니다.
  • offset은 음수면 0으로, 1,000,000을 넘으면 1,000,000으로 맞춰집니다.

2. 같은 초에 수집된 자산들의 페이지 순서가 정해져 있지 않았습니다

페이지를 나누려면 행 사이에 흔들리지 않는 순서가 있어야 합니다. 정렬은
last_seen_at DESC 하나뿐이었는데, 한 번에 수집된 자산들은 이 값을 초 단위까지
공유합니다.
그 안에서의 순서는 엔진이 정하게 남아 있었고, 그대로 페이지를
걸었다면 같은 자산이 두 페이지에 나타나고 다른 자산은 어느 페이지에도 나타나지
않았을 것입니다.

정렬에 id가 동점 처리로 더해져 순서가 전순서가 되었습니다. 페이지를 도입하는
같은 변경에서 함께 고쳤으므로, 이 증상은 릴리즈된 적이 없습니다.

3. 행을 읽다 끊긴 질의가 200으로 돌아갔습니다

결과 행을 훑는 반복문이 rows.Err()를 확인하지 않았습니다. 반복 도중 연결이
끊기거나 스캔이 실패하면 반복은 조용히 끝나고, 그때까지 모인 행이 정상 응답으로
나갔습니다 — 오류 없이 짧아진 목록입니다. 이제 반복이 끝난 뒤 오류를 확인하고,
있으면 500으로 답합니다.

검증

  • 끝까지 걸어 보았습니다. 한도보다 많은 자산을 만들고 next_offset으로 이어
    받아 전체가 중복 없이, 빠짐없이 모이는지, total이 맞은 수와 같은지,
    마지막 페이지에서 has_morefalse가 되는지를 고정했습니다.
  • 경계에서. 결과 끝을 지난 offset이 빈 목록과 has_more false를 돌려주면서도
    total은 여전히 맞은 수를 말하는지, 결과가 정확히 한도에서 끝날 때
    has_morefalse인지(한 행을 더 읽고 버리는 방식)를 고정했습니다.
  • 동점 순서. last_seen_at을 공유하는 자산들에 대한 페이지 순회 테스트를
    회귀 방어용으로 남겼습니다.
  • 되돌려 확인했습니다. 수정을 되돌리면 위 테스트들이 정확히 그 지점에서
    실패합니다.
  • 저장 모드 양쪽에서. go test ./...가 SQLite fallback과 실제
    PostgreSQL(scripts/test-postgres.sh) 양쪽에서 전 패키지 통과하고,
    go vet·go build·gofmt가 통과합니다.
  • 계약 문서. openapi.yamlQueryInput.offset과 두 execute 엔드포인트의 새
    응답 필드를 기술했고, @redocly/cli@2.47.0 lint의 경고 수가 변경 전과 같은
    6개(모두 기존 것)임을 확인했습니다. docs/API_MCP_GUIDE.md에 페이징 설명과 curl
    예시를 넣었습니다.

호환성

  • 데이터베이스 마이그레이션이 없습니다.
  • 응답에 키가 추가되기만 했습니다. items·count·ast·limit·truncated
    이름도 뜻도 값도 그대로이고, offset·total·has_more·next_offset
    더해졌습니다. 관리 콘솔은 itemstruncated만 읽으므로 영향이 없습니다.
  • offset을 주지 않는 요청은 예전과 똑같이 첫 페이지를 받습니다.
  • 알려진 제한. 콘솔의 Query DSL 화면은 아직 total·offset을 쓰지 않아 첫
    페이지만 보여 줍니다. 전체 순회는 REST·API key 호출자에게 열려 있습니다.
  • MCP 도구, REST의 다른 엔드포인트, scope는 바뀌지 않았습니다.
  • Agent(Rust) 동작은 이번 릴리즈에서 바뀌지 않았습니다.