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

Transaction lock timeout error #8105

Open
onurdialpad opened this issue Jan 8, 2025 · 0 comments
Open

Transaction lock timeout error #8105

onurdialpad opened this issue Jan 8, 2025 · 0 comments

Comments

@onurdialpad
Copy link

[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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants