-
Notifications
You must be signed in to change notification settings - Fork 1k
Open
Description
[REQUIRED] Environment info
firebase-tools: 13.29.1
Platform: macOS
[REQUIRED] Test case
#!/usr/bin/env python3
import requests
import json
import sys
def main():
# Update these values based on your environment and project setup:
EMULATOR_HOST = "127.0.0.1:54510" # Where your Firestore/Datastore emulator is running
PROJECT_ID = "testbed-test" # Your GCP project ID
# 1. Construct the Datastore REST API endpoint for "lookup"
lookup_url = f"http://{EMULATOR_HOST}/v1/projects/{PROJECT_ID}:lookup"
# 2. Build the request body for the Datastore v1 "lookup"
# We use readOptions.newTransaction to start a new read-write transaction
lookup_payload = {
"readOptions": {
"newTransaction": {
"readWrite": {}
}
},
"keys": [
{
"path": [
{
"kind": "TestKind",
"name": "TestKey"
}
]
}
]
}
print("[LOOKUP REQUEST BODY]")
print(json.dumps(lookup_payload, indent=2))
# 3. Send the lookup request
lookup_resp = requests.post(lookup_url, json=lookup_payload)
print("\n[LOOKUP RESPONSE]")
print("Status Code:", lookup_resp.status_code)
print("Body:", lookup_resp.text)
# 4. Parse out the transaction ID from the lookup response
# According to the Datastore docs, if you start a transaction,
# the response will include a 'transaction' field.
if lookup_resp.status_code != 200:
print("Lookup request failed; cannot proceed.")
sys.exit(1)
lookup_data = lookup_resp.json()
transaction_id = lookup_data.get("transaction")
if not transaction_id:
print("No transaction ID returned in lookup response. Exiting.")
sys.exit(1)
print(f"\nExtracted Transaction ID: {transaction_id}")
# 5. Now use this transaction ID in a commit request
commit_url = f"http://{EMULATOR_HOST}/v1/projects/{PROJECT_ID}:commit"
# Example mutation: upsert an entity with the same key used in the lookup
commit_payload = {
"mode": "TRANSACTIONAL",
"transaction": transaction_id,
"mutations": [
{
"upsert": {
"key": {
"partitionId": {
"projectId": PROJECT_ID,
"namespaceId": ""
},
"path": [
{
"kind": "TestKind",
"name": "TestKey"
}
]
},
"properties": {
"exampleField": {
"stringValue": "Hello from transaction"
}
}
}
}
]
}
print("\n[COMMIT REQUEST BODY]")
print(json.dumps(commit_payload, indent=2))
commit_resp = requests.post(commit_url, json=commit_payload)
print("\n[COMMIT RESPONSE]")
print("Status Code:", commit_resp.status_code)
print("Body:", commit_resp.text)
if commit_resp.status_code == 200:
commit_data = commit_resp.json()
print("\nCommit Response JSON:")
print(json.dumps(commit_data, indent=2))
else:
print("Commit request failed.")
if __name__ == "__main__":
main()
[REQUIRED] Steps to reproduce
When I use firestore emulator in datastore emulator mode to test the example script, it gives error while it works perfectly with Datasatore emulator
[REQUIRED] Expected behavior
Datastore emulator's response is: (the last part of it)
[COMMIT RESPONSE]
Status Code: 200
Body: {
"mutationResults": [{
"version": "2"
}],
"commitVersion": "2"
}
Commit Response JSON:
{
"mutationResults": [
{
"version": "2"
}
],
"commitVersion": "2"
}
[REQUIRED] Actual behavior
Firestore emulator's response is:
[COMMIT RESPONSE]
Status Code: 409
Body: {"error":{"code":409,"message":"Transaction lock timeout.","status":"ABORTED"}}
Commit request failed.