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

Incorrect outbox metadata example for Python #4506

Open
jseguillon opened this issue Jan 30, 2025 · 2 comments
Open

Incorrect outbox metadata example for Python #4506

jseguillon opened this issue Jan 30, 2025 · 2 comments
Assignees
Labels
content/incorrect-information Content in the docs is incorrect
Milestone

Comments

@jseguillon
Copy link

Describe the issue

Example for outbox in python seems to be errored. It assumes we can, via python SDK, do:

  await client.state.transaction(DAPR_STORE_NAME, ops);

but:

== APP ==     c.state.save(
== APP == AttributeError: 'DaprClient' object has no attribute 'state'

Indeed python SDK does not provide this state attribute.

So I tried:

    c.save_state(
        store_name=DAPR_STORE_NAME,
        key="test",
        value='{ "say": "hello world from outbox-metadata" }',
        state_metadata={  "outbox.projection": "true" },
        metadata=(("outbox.projection", "true"),)
    )

But despite my efforts in injecting metadatas, I could not see any outbox message in my outbox topic.

Only way I found to get a message in outbox topic is to use transactions:

    transaction_operation = TransactionalStateOperation(
        operation_type=TransactionOperationType.upsert,
        key="1",
        data='{ "say": "hello world from outbox transaction" }',
    )

    c.execute_state_transaction(
        store_name=DAPR_STORE_NAME,
        operations=[transaction_operation],
        transactional_metadata={ 'datacontenttype': 'application/json'},
        metadata= (('datacontenttype', 'application/json'),)
    )

I made this project where you can find full code and logs: https://github.com/jseguillon/dapr-outbox-python

URL of the docs

https://github.com/dapr/docs/blob/v1.14/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-outbox.md?plain=1#L205

Expected content

A working Python example for outbox with metadata like example for others langages

Screenshots

metadata:

Image

transaction:

Image

Additional context

@jseguillon jseguillon added the content/incorrect-information Content in the docs is incorrect label Jan 30, 2025
@hhunter-ms hhunter-ms added this to the 1.15 milestone Feb 7, 2025
@msfussell
Copy link
Member

@jseguillon Appreciate you taking the time to raise this issue. Yes you are correct , the example is wrong. Can I suggest

  1. That the sample in docs https://docs.dapr.io/developing-applications/building-blocks/state-management/howto-outbox/#shape-the-outbox-pattern-message is updated with
@app.post('/state-outbox-transaction')
def outbox_transaction():
    from dapr.clients.grpc._request import TransactionalStateOperation, TransactionOperationType, DaprRequest

    transaction_operation = TransactionalStateOperation(
        operation_type=TransactionOperationType.upsert,
        key="1",
        data='{ "say": "hello world from outbox transaction" }',
    )

    print("/state-outbox-transaction: Execute the state transaction")
    c.execute_state_transaction(
        store_name=DAPR_STORE_NAME,
        operations=[transaction_operation],
        transactional_metadata={ 'datacontenttype': 'application/json'},
        metadata= (('datacontenttype', 'application/json'),)
    )
    
    print("/state-outbox-transaction: Transaction executed")
    return JSONResponse(content={"success": "true"})

Have to update the code here https://docs.dapr.io/developing-applications/building-blocks/state-management/howto-outbox/#override-dapr-generated-cloudevent-fields also

Feel free to do a docs contribution is you like

  1. I raised this issue in the Python SDK repo Create Outbox Sample python-sdk#790 and it would be amazing it you could raise a PR contribution for this.

@elena-kolevska
Copy link
Contributor

By configuring the state store, you can use the outbox pattern without any additional metadata in the requests. For example:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: localhost:6379
  - name: redisPassword
    value: ""
  - name: actorStateStore
    value: "true"
  - name: outboxPublishPubsub
    value: "pubsub". # This is the pubsub component name
  - name: outboxPublishTopic
    value: "test"

The additional metadata fields are needed to combine outbox and non-outbox messages on the same state store. Unfortunately, we currently don't support adding metadata for TransactionalStateOperation in the python-sdk, but I opened a PR here which will allow you to do something like:

from dapr.clients import DaprClient
from dapr.clients.grpc._request import TransactionalStateOperation, TransactionOperationType

DAPR_STORE_NAME = "statestore"

with DaprClient() as d:

    d.execute_state_transaction(store_name=DAPR_STORE_NAME, operations=[
        TransactionalStateOperation(key="key1", data="val1", metadata={"outbox.projection": "false"}),
        TransactionalStateOperation(key="key1", data="val2", metadata={"outbox.projection": "true"}),
    ],)

    print("Transaction with outbox pattern executed successfully!")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
content/incorrect-information Content in the docs is incorrect
Projects
None yet
Development

No branches or pull requests

4 participants