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

client.account.public_folders_root.walk() takes a long time #1354

Open
JohannFaust666 opened this issue Feb 5, 2025 · 1 comment
Open

client.account.public_folders_root.walk() takes a long time #1354

JohannFaust666 opened this issue Feb 5, 2025 · 1 comment

Comments

@JohannFaust666
Copy link

JohannFaust666 commented Feb 5, 2025

When I'm using client.public_folders_root.walk() in my FastAPI endpoint it blocks all other requests until walk() has completed its work (usually it takes 5-10 minutes).

It takes 5-10 minutes to enter in the loop, example:

# processes for a long time before the cycle
for folder in client.account.public_folders_root.walk():
    # entered the loop
    print(folder.name)

But after entering the loop everything is ok.

I tried to use await to_thread(client.public_folders_root.walk) but it blocks anyway. How can I add it to the async thread or process not the whole walk() but chunks?

My ExchangeClient code:

class ExchangeClient:
    def __init__(self):
        self.account: Optional[Account] = None
        self._init_account()

    def _validate_env_vars(self):
        required_vars = [
            'EXCHANGE_USERNAME',
            'EXCHANGE_PASSWORD',
            'EXCHANGE_SERVER',
            'EXCHANGE_EMAIL'
        ]
        missing_vars = [var for var in required_vars if not os.getenv(var)]
        if missing_vars:
            raise RuntimeError(f"Missing required environment variables: {', '.join(missing_vars)}")

    def _init_account(self):
        self._validate_env_vars()
        
        try:
            credentials = Credentials(
                username=os.getenv('EXCHANGE_USERNAME'),
                password=os.getenv('EXCHANGE_PASSWORD')
            )
            config = Configuration(
                server=os.getenv('EXCHANGE_SERVER'),
                credentials=credentials
            )
            self.account = Account(
                primary_smtp_address=os.getenv('EXCHANGE_EMAIL'),
                config=config,
                autodiscover=False,
                access_type=DELEGATE
            )
            logger.info("Successfully connected to Exchange account")
        except Exception as e:
            logger.error(f"Failed to initialize Exchange account: {str(e)}")
            raise
@ecederstrand
Copy link
Owner

walk() is not a generator, which is why you have to wait until all subfolders have been collected. It's not trivial to change that, but dive into _walk() and try to change it, if you're comfortable with diving into exchangelib code.

The reason is especially slow for public folders is that deep searching in public folders is not supported by EWS, so we have to send one API call for every subfolder in the folder hierachy.

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

2 participants