Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Schema Version #131

Merged
merged 4 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions fauna/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ def _query(
query_tags = QueryTags.decode(
dec["query_tags"]) if "query_tags" in dec else None
txn_ts = dec["txn_ts"] if "txn_ts" in dec else None
schema_version = dec["schema_version"] if "schema_version" in dec else None
traceparent = headers.get("traceparent", None)
static_type = dec["static_type"] if "static_type" in dec else None

Expand All @@ -327,6 +328,7 @@ def _query(
summary=summary,
traceparent=traceparent,
txn_ts=txn_ts,
schema_version=schema_version,
)

def _check_protocol(self, response_json: Any, status_code):
Expand Down Expand Up @@ -361,6 +363,7 @@ def _handle_error(self, body: Any, status_code: int):
body["query_tags"]) if "query_tags" in body else None
stats = QueryStats(body["stats"]) if "stats" in body else None
txn_ts = body["txn_ts"] if "txn_ts" in body else None
schema_version = body["schema_version"] if "schema_version" in body else None
summary = body["summary"] if "summary" in body else None

constraint_failures: Optional[List[ConstraintFailure]] = None
Expand All @@ -384,6 +387,7 @@ def _handle_error(self, body: Any, status_code: int):
query_tags=query_tags,
stats=stats,
txn_ts=txn_ts,
schema_version=schema_version,
)
elif code == "invalid_request":
raise InvalidRequestError(
Expand All @@ -395,6 +399,7 @@ def _handle_error(self, body: Any, status_code: int):
query_tags=query_tags,
stats=stats,
txn_ts=txn_ts,
schema_version=schema_version,
)
elif code == "abort":
abort = err["abort"] if "abort" in err else None
Expand All @@ -408,6 +413,7 @@ def _handle_error(self, body: Any, status_code: int):
query_tags=query_tags,
stats=stats,
txn_ts=txn_ts,
schema_version=schema_version,
)

else:
Expand All @@ -420,6 +426,7 @@ def _handle_error(self, body: Any, status_code: int):
query_tags=query_tags,
stats=stats,
txn_ts=txn_ts,
schema_version=schema_version,
)
elif status_code == 401:
raise AuthenticationError(
Expand All @@ -431,6 +438,7 @@ def _handle_error(self, body: Any, status_code: int):
query_tags=query_tags,
stats=stats,
txn_ts=txn_ts,
schema_version=schema_version,
)
elif status_code == 403:
raise AuthorizationError(
Expand All @@ -442,6 +450,7 @@ def _handle_error(self, body: Any, status_code: int):
query_tags=query_tags,
stats=stats,
txn_ts=txn_ts,
schema_version=schema_version,
)
elif status_code == 429:
raise ThrottlingError(
Expand All @@ -453,6 +462,7 @@ def _handle_error(self, body: Any, status_code: int):
query_tags=query_tags,
stats=stats,
txn_ts=txn_ts,
schema_version=schema_version,
)
elif status_code == 440:
raise QueryTimeoutError(
Expand All @@ -464,6 +474,7 @@ def _handle_error(self, body: Any, status_code: int):
query_tags=query_tags,
stats=stats,
txn_ts=txn_ts,
schema_version=schema_version,
)
elif status_code == 500:
raise ServiceInternalError(
Expand All @@ -475,6 +486,7 @@ def _handle_error(self, body: Any, status_code: int):
query_tags=query_tags,
stats=stats,
txn_ts=txn_ts,
schema_version=schema_version,
)
elif status_code == 503:
raise ServiceTimeoutError(
Expand All @@ -486,6 +498,7 @@ def _handle_error(self, body: Any, status_code: int):
query_tags=query_tags,
stats=stats,
txn_ts=txn_ts,
schema_version=schema_version,
)
else:
raise ServiceError(
Expand All @@ -497,6 +510,7 @@ def _handle_error(self, body: Any, status_code: int):
query_tags=query_tags,
stats=stats,
txn_ts=txn_ts,
schema_version=schema_version,
)

def _set_endpoint(self, endpoint):
Expand Down
20 changes: 18 additions & 2 deletions fauna/encoding/wire_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,26 +95,35 @@ def stats(self) -> QueryStats:

@property
def txn_ts(self) -> int:
"""The last transaction timestamp of the query. A Unix epoch in microseconds."""
return self._txn_ts

@property
def schema_version(self) -> int:
"""The schema version that was used for the query execution."""
return self._schema_version

def __init__(
self,
query_tags: Optional[Mapping[str, str]] = None,
stats: Optional[QueryStats] = None,
summary: Optional[str] = None,
txn_ts: Optional[int] = None,
schema_version: Optional[int] = None,
):
self._query_tags = query_tags or {}
self._stats = stats or QueryStats({})
self._summary = summary or ""
self._txn_ts = txn_ts or 0
self._schema_version = schema_version or 0

def __repr__(self):
return f"{self.__class__.__name__}(" \
f"query_tags={repr(self.query_tags)}," \
f"stats={repr(self.stats)}," \
f"summary={repr(self.summary)}," \
f"txn_ts={repr(self.txn_ts)})"
f"txn_ts={repr(self.txn_ts)}," \
f"schema_version={repr(self.schema_version)})"


class QuerySuccess(QueryInfo):
Expand Down Expand Up @@ -144,10 +153,16 @@ def __init__(
summary: Optional[str],
traceparent: Optional[str],
txn_ts: Optional[int],
schema_version: Optional[int],
):

super().__init__(
query_tags=query_tags, stats=stats, summary=summary, txn_ts=txn_ts)
query_tags=query_tags,
stats=stats,
summary=summary,
txn_ts=txn_ts,
schema_version=schema_version,
)

self._traceparent = traceparent
self._static_type = static_type
Expand All @@ -161,6 +176,7 @@ def __repr__(self):
f"summary={repr(self.summary)}," \
f"traceparent={repr(self.traceparent)}," \
f"txn_ts={repr(self.txn_ts)}," \
f"schema_version={repr(self.schema_version)}," \
f"data={repr(self.data)})"


Expand Down
2 changes: 2 additions & 0 deletions fauna/errors/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,15 @@ def __init__(
query_tags: Optional[Mapping[str, str]] = None,
stats: Optional[QueryStats] = None,
txn_ts: Optional[int] = None,
schema_version: Optional[int] = None,
):
QueryInfo.__init__(
self,
query_tags=query_tags,
stats=stats,
summary=summary,
txn_ts=txn_ts,
schema_version=schema_version,
)

FaunaError.__init__(
Expand Down
14 changes: 13 additions & 1 deletion tests/integration/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import pytest

from fauna import fql, Page, NullDocument
from fauna import fql, Page, NullDocument, Module
from fauna.client import Client, QueryOptions
from fauna.errors import QueryCheckError, QueryRuntimeError, AbortError, ClientError, QueryTimeoutError
from fauna.encoding import ConstraintFailure
Expand All @@ -18,6 +18,7 @@ def test_query_smoke_test(subtests, client):
assert res.stats.compute_ops > 0
assert res.traceparent != ""
assert res.summary == ""
assert res.schema_version > 0

with subtests.test(msg="with debug"):
res = client.query(fql('dbg("Hello, World")'))
Expand Down Expand Up @@ -136,3 +137,14 @@ def test_query_timeout(client, a_collection):
client.query(
fql("${coll}.byId('123')", coll=a_collection),
QueryOptions(query_timeout=timedelta(milliseconds=1)))


def test_query_schema_version(client):
coll_name = "schemaVersionTestColl"

_ = client.query(fql("Collection.byName(${coll})?.delete()", coll=coll_name))
r = client.query(fql("Collection.create({ name: ${name} })", name=coll_name))
expected_schema_version = r.txn_ts

r = client.query(fql("${mod}.all()", mod=Module(coll_name)))
assert expected_schema_version == r.schema_version
8 changes: 7 additions & 1 deletion tests/unit/test_wire_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def test_query_success_repr():
summary="human readable",
traceparent=None,
txn_ts=123,
schema_version=123,
)
stats = "{'compute_ops': 1, 'read_ops': 0, 'write_ops': 0, " \
"'query_time_ms': 0, 'storage_bytes_read': 0, 'storage_bytes_write': 0, " \
Expand All @@ -20,10 +21,12 @@ def test_query_success_repr():
"summary='human readable'," \
"traceparent=None," \
"txn_ts=123," \
"schema_version=123," \
"data={'foo': 'bar'})"

evaluated: QuerySuccess = eval(repr(qs))
assert evaluated.txn_ts == qs.txn_ts
assert evaluated.schema_version == qs.schema_version
assert evaluated.traceparent == qs.traceparent
assert evaluated.query_tags == qs.query_tags
assert evaluated.data == qs.data
Expand All @@ -38,20 +41,23 @@ def test_query_info_repr():
stats=QueryStats({'compute_ops': 1}),
summary="human readable",
txn_ts=123,
schema_version=123,
)
stats = "{'compute_ops': 1, 'read_ops': 0, 'write_ops': 0, " \
"'query_time_ms': 0, 'storage_bytes_read': 0, 'storage_bytes_write': 0, " \
"'contention_retries': 0}"
assert repr(qi) == "QueryInfo(query_tags={'tag': 'value'}," \
f"stats=QueryStats(stats={stats})," \
"summary='human readable'," \
"txn_ts=123)"
"txn_ts=123," \
"schema_version=123)"

evaluated: QueryInfo = eval(repr(qi))
assert evaluated.txn_ts == qi.txn_ts
assert evaluated.query_tags == qi.query_tags
assert evaluated.summary == qi.summary
assert evaluated.stats == qi.stats
assert evaluated.schema_version == qi.schema_version


def test_query_stats_repr():
Expand Down