Skip to content

docs/emitter-design: give ReturnShape a value for scalar, binary, union and map responses #952

Closed

Description

@OmarAlJarrah

Problem

§3.1 gives ReturnShape four values, model | void | list_elementwise | stream, and makes ReturnType the "unwrapped primary return type". A success response whose body is a scalar, binary data, a union or a map has no value to take:

openapi: 3.1.0
info: {title: t, version: "1"}
paths:
  /count:
    get:
      operationId: count
      responses:
        "200": {description: ok, content: {application/json: {schema: {type: integer}}}}
  /file:
    get:
      operationId: download
      responses:
        "200": {description: ok, content: {application/octet-stream: {schema: {type: string, format: binary}}}}
  /pet:
    get:
      operationId: getPet
      responses:
        "200":
          description: ok
          content:
            application/json:
              schema:
                oneOf:
                  - {type: object, properties: {bark: {type: string}}, required: [bark]}
                  - {type: object, properties: {meow: {type: string}}, required: [meow]}
  /labels:
    get:
      operationId: labels
      responses:
        "200": {description: ok, content: {application/json: {schema: {type: object, additionalProperties: {type: string}}}}}
  /purge:
    post:
      operationId: purge
      responses:
        default: {description: an error, content: {application/json: {schema: {type: object, properties: {message: {type: string}}}}}}

At c387e25c the first four bodies lower to an integer primitive, a bytes primitive, a union and a map. purge has no success response at all: its only response, default, lowers as an error (#608), and the plan does not say what Return an operation with no success response takes.

The golden spec here is the Cloudflare API schema (cloudflare/api-schemas openapi.json at 911ad78), compiled with go run ./cmd/morphic compile openapi.json -o golden.ir.json at c387e25c. That command exits 1 on four unrelated errors and still writes the document. Taking each operation's first success response and its first content under the design's json > form > multipart > binary ranking, 59 of its 3,761 operations return a body that ReturnShape cannot describe: 26 scalars, 14 binary, 16 unions and 3 maps. Another 42 operations have no success response: 32 whose only response is default, and 10 that declare only 4xx responses.

The count
import json, sys, collections
d = json.load(open(sys.argv[1])); T = d["types"]
def ops(groups):
    for g in groups:
        yield from g.get("operations") or []; yield from ops(g.get("groups") or [])
def rank(c):  # the design's default ranking: json > form > multipart > binary
    m = c.get("mediaType", "")
    return 0 if "json" in m else 1 if "x-www-form-urlencoded" in m else 2 if "multipart/" in m else 3
def shape(t):
    k = t.get("kind")
    if k == "scalar":
        t = T.get((t.get("base") or {}).get("target"), {}); k = t.get("kind")
    if k == "primitive":
        return "binary" if t.get("prim") == "bytes" else "scalar"
    return k
out = collections.Counter()
for s in d["services"]:
    for o in ops(s.get("groups") or []):
        rs = o.get("responses") or []
        if not rs: out["no success response"] += 1; continue
        cs = (rs[0].get("payload") or {}).get("contents") or []
        if not cs: out["void"] += 1; continue
        c = min(cs, key=rank)
        out[shape(T.get((c.get("type") or {}).get("target"), {}))] += 1
print(dict(out))

Direction

A proposal:

  • Widen ReturnShape, or replace it with the primary return type plus how the body is read. Binary data is read as a stream of bytes, not decoded, so it takes a value of its own.
  • State the Return of an operation with no success response.
  • Add a §8 walkthrough line for each.
  • Done when every operation of the golden spec gets a Return from a rule the design states.

Out of scope

Which response is primary, a rule §3.5 already gives. Envelope unwrapping is #695.

Related: #608, #695

Priority: P1, rule 5 (direct impact: an emitter-plan contract gap on the golden spec's output). python3 returns.py golden.ir.json (above) → scalar: 26, binary: 14, union: 16, map: 3, no success response: 42 of 3,761 operations (spec @911ad78, morphic @c387e25c).

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority:P1Core first-emitter feature on mainstream specstype:docsDocumentation only

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions