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

Adding Line Items is really slow #9

Open
JanBlmr opened this issue Aug 21, 2023 · 0 comments
Open

Adding Line Items is really slow #9

JanBlmr opened this issue Aug 21, 2023 · 0 comments

Comments

@JanBlmr
Copy link

JanBlmr commented Aug 21, 2023

Hi there,

we are using async-stripe for creating invoices (FastAPI service)

import backoff
from async_stripe import stripe
from stripe.error import RateLimitError

from app import settings

class StripeClient:
    def __init__(self, api_key: str = settings.STRIPE_API_KEY) -> None:
        stripe.api_key = api_key
        stripe.api_version = settings.STRIPE_API_VERSION
        if settings.ENVIRONMENT not in ("dev", "prod") and settings.STRIPE_MOCK_API_BASE:
            stripe.api_base = settings.STRIPE_MOCK_API_BASE

    @backoff.on_exception(backoff.expo, RateLimitError, max_time=3, max_tries=4)
    async def draft_invoice(
        self,
        customer: str,
        statement_descriptor: str,
        description: str,
        metadata: dict,
        discounts: list[dict],
        currency: str,
        default_source: str | None = None,
    ) -> stripe.Invoice:
        return await stripe.Invoice.create(
            customer=customer,
            statement_descriptor=statement_descriptor,
            currency=currency.lower(),
            description=description,
            metadata=metadata,
            discounts=[discounts] or None,
            default_source=default_source,
        )

    @backoff.on_exception(backoff.expo, RateLimitError, max_time=3, max_tries=4)
    async def finalize_invoice(self, invoice_id: str) -> stripe.Invoice:
        return await stripe.Invoice.finalize_invoice(invoice_id)

    @backoff.on_exception(backoff.expo, RateLimitError, max_time=3, max_tries=4)
    async def pay_invoice(self, invoice_id: str, paid_out_of_band: bool = False) -> stripe.Invoice:
        pay_params = {}
        if paid_out_of_band:
            pay_params["paid_out_of_band"] = paid_out_of_band

        return await stripe.Invoice.pay(invoice_id, **pay_params)

    async def add_invoice_item(
        self,
        invoice_id: str,
        customer_id: str,
        quantity: int,
        metadata: dict,
        tax_rates: list[str],
        discountable: bool,
        unit_amount: int,
        product_id: str,
        currency: str,
    ) -> stripe.InvoiceItem:
        return await stripe.InvoiceItem.create(
            customer=customer_id,
            currency=currency,
            quantity=quantity,
            metadata=metadata,
            tax_rates=tax_rates,
            discountable=discountable,
            invoice=invoice_id,
            price_data=dict(
                unit_amount=unit_amount,
                currency=currency,
                product=product_id,
            ),
        )

Here is how the function looks like that we are using for creating the invoice:

async def process_invoice(self, invoice_request: InvoiceRequest) -> stripe.Invoice:
        invoice = await self.stripe_client.draft_invoice(
            customer=invoice_request.customer_id,
            description=invoice_request.description,
            metadata=invoice_request.metadata,
            statement_descriptor=invoice_request.statement_descriptor,
            currency=invoice_request.currency,
            discounts=invoice_request.discounts,
            default_source=invoice_request.default_source,
        )

        for invoice_line in invoice_request.lines:
            await self.stripe_client.add_invoice_item(
                invoice_id=invoice.id,
                customer_id=invoice_request.customer_id,
                product_id=invoice_line.product_id,
                quantity=invoice_line.quantity,
                unit_amount=invoice_line.unit_amount,
                tax_rates=invoice_line.tax_rates,
                discountable=invoice_line.discountable,
                metadata=invoice_line.metadata,
                currency=invoice_request.currency,
            )

        invoice = await self.stripe_client.finalize_invoice(invoice_id=invoice.id)

        await self.stripe_client.pay_invoice(invoice_id=invoice.id)

As you can see in the screenshot, adding the invoices takes a really long timer, much longer than when doing the same with the official stripe library (almost 12 seconds)

Screenshot 2023-08-21 at 11 16 04

We also tried this, but same issue:

add_line_items_tasks = []

for invoice_line in invoice_request.lines:
    task = asyncio.ensure_future(
        self.stripe_client.add_invoice_item(
            invoice_id=invoice.id,
            customer_id=invoice_request.customer_id,
            product_id=invoice_line.product_id,
            quantity=invoice_line.quantity,
            unit_amount=invoice_line.unit_amount,
            tax_rates=invoice_line.tax_rates,
            discountable=invoice_line.discountable,
            metadata=invoice_line.metadata,
            currency=invoice_request.currency,
        )
    add_line_items_tasks.append(task)

await asyncio.gather(*add_line_items_tasks)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant