long2ice/meilisync

TypeError: 'async for' requires an object with __aiter__ method, got coroutine

kansoadi opened this issue · 24 comments

For syncing databases with PostgreSQL and Meilisync,

I installed and configured Meilisync (windows 10) by following the steps in https://www.meilisearch.com/docs/learn/cookbooks/meilisync_postgresql
Meilisync was well-configured:
1- image (1)
2- but for the Meilisync start, i received
TypeError: 'async for' requires an object with aiter method, got generator
returned from
C:\Python312\Lib\site-packages\meilisync\main.py:96 in _ │
│ │
│ 93 │ │ for sync in settings.sync: │
│ 94 │ │ │ if sync.full and not await meili.index_exists(sync.index_name): │
│ 95 │ │ │ │ count = 0 │
│ > 96 │ │ │ │ async for items in await source.get_full_data(sync, meili_settings.inser │
│ 97 │ │ │ │ │ count += len(items) │
│ 98 │ │ │ │ │ await meili.add_data(sync, items) │
│ 99 │ │ │ │ if count:

image

image (2)
the config.yml:

meilisearch:
  api_url: http://localhost:7700/
  api_key: '_API KEY_'
  insert_size: 1000
  insert_interval: 10

source:
  type: postgres
  host: 127.0.0.1
  port: 5432
  database: _DATABASE NAME_
  user: postgres
  password: root

progress:
  type: file  
  path: 'C:\\Python312\\Lib\\site-packages\\meilisync\\progress.json'

sync:
 
  - table: bookings
    index: bookings
    full: true
   
debug: true

kindly, Any idea on how to solve this issue?

i solved the problem related to the

"get_full_data(sync, meili_settings.insert_size)"

but i got a new one

TypeError: 'async for' received an object from aiter that does not implement anext: coroutine

meilisync start
C:\Python312\Lib\site-packages\meilisync\main.py:135: RuntimeWarning: coroutine 'Source.aiter' was never awaited
async for event in source:
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
┌─────────────────────────────── Traceback (most recent call last) ────────────────────────────────┐
│ C:\Python312\Lib\site-packages\meilisync\main.py:174 in start │
│ │
│ 171 │ │ lock = asyncio.Lock() │
│ 172 │ │ await asyncio.gather(
(), interval()) │
│ 173 │ │
│ > 174 │ asyncio.run(run()) │
│ 175 │
│ 176 │
│ 177 @app.command(help="Refresh all data by swap index") │
│ │
│ ┌─────────────────────────────────────────── locals ───────────────────────────────────────────┐ │
│ │ _ = <function start.._ at 0x0000020673F679C0> │ │
│ │ collection = <meilisync.event.EventCollection object at 0x00000206739D0260> │ │
│ │ context = <click.core.Context object at 0x0000020673D97410> │ │
│ │ current_progress = {'start_lsn': '0/EE4E258'} │ │
│ │ interval = <function start..interval at 0x0000020673F67BA0> │ │
│ │ lock = <asyncio.locks.Lock object at 0x0000020673F6EDB0 [unlocked]> │ │
│ │ meili = <meilisync.meili.Meili object at 0x00000206735B7F80> │ │
│ │ meili_settings = MeiliSearch( │ │
│ │ │ api_url='http://localhost:7700/', │ │
│ │ │ api_key='API KEY', │ │
│ │ │ insert_size=1000, │ │
│ │ │ insert_interval=10 │ │
│ │ ) │ │
│ │ progress = <meilisync.progress.file.File object at 0x00000206738EF260> │ │
│ │ run = <function start..run at 0x0000020673F37060> │ │
│ │ settings = Settings( │ │
│ │ │ plugins=[], │ │
│ │ │ progress=Progress( │ │
│ │ │ │ type=<ProgressType.file: 'file'>, │ │
│ │ │ │ │ │
│ │ path='C:\\Python312\\Lib\\site-packages\\meilisync\\progress.j… │ │
│ │ │ ), │ │
│ │ │ debug=True, │ │
│ │ │ source=Source( │ │
│ │ │ │ type=<SourceType.postgres: 'postgres'>, │ │
│ │ │ │ database='DATABASE NAME', │ │
│ │ │ │ host='127.0.0.1', │ │
│ │ │ │ port=5432, │ │
│ │ │ │ user='postgres', │ │
│ │ │ │ password='root' │ │
│ │ │ ), │ │
│ │ │ meilisearch=MeiliSearch( │ │
│ │ │ │ api_url='http://localhost:7700/', │ │
│ │ │ │ api_key='API KEY', │ │
│ │ │ │ insert_size=1000, │ │
│ │ │ │ insert_interval=10 │ │
│ │ │ ), │ │
│ │ │ sync=[ │ │
│ │ │ │ Sync( │ │
│ │ │ │ │ plugins=[], │ │
│ │ │ │ │ table='booking', │ │
│ │ │ │ │ pk='id', │ │
│ │ │ │ │ full=True, │ │
│ │ │ │ │ index='booking', │ │
│ │ │ │ │ fields=None │ │
│ │ │ │ ) │ │
│ │ │ ], │ │
│ │ │ sentry=None │ │
│ │ ) │ │
│ │ source = <meilisync.source.postgres_old.Postgres object at 0x00000206734A7DA0> │ │
│ └──────────────────────────────────────────────────────────────────────────────────────────────┘ │
│ │
│ C:\Python312\Lib\asyncio\runners.py:194 in run │
│ │
│ 191 │ │ │ "asyncio.run() cannot be called from a running event loop") │
│ 192 │ │
│ 193 │ with Runner(debug=debug, loop_factory=loop_factory) as runner: │
│ > 194 │ │ return runner.run(main) │
│ 195 │
│ 196 │
│ 197 def _cancel_all_tasks(loop): │
│ │
│ ┌────────────────────────────────── locals ──────────────────────────────────┐ │
│ │ debug = None │ │
│ │ loop_factory = None │ │
│ │ main = <coroutine object start..run at 0x0000020673EEFE60> │ │
│ │ runner = <asyncio.runners.Runner object at 0x0000020670DFB6E0> │ │
│ └────────────────────────────────────────────────────────────────────────────┘ │
│ │
│ C:\Python312\Lib\asyncio\runners.py:118 in run │
│ │
│ 115 │ │ │
│ 116 │ │ self._interrupt_count = 0 │
│ 117 │ │ try: │
│ > 118 │ │ │ return self._loop.run_until_complete(task) │
│ 119 │ │ except exceptions.CancelledError: │
│ 120 │ │ │ if self.interrupt_count > 0: │
│ 121 │ │ │ │ uncancel = getattr(task, "uncancel", None) │
│ │
│ ┌─────────────────────────────────────────── locals ───────────────────────────────────────────┐ │
│ │ context = <contextvars.Context object at 0x0000020673D20B00> │ │
│ │ coro = <coroutine object start..run at 0x0000020673EEFE60> │ │
│ │ self = <asyncio.runners.Runner object at 0x0000020670DFB6E0> │ │
│ │ sigint_handler = functools.partial(<bound method Runner.on_sigint of │ │
│ │ <asyncio.runners.Runner object at 0x0000020670DFB6E0>>, main_task=<Task │ │
│ │ finished name='Task-4' coro=<start..run() done, defined at │ │
│ │ C:\Python312\Lib\site-packages\meilisync\main.py:169> │ │
│ │ exception=TypeError("'async for' received an object from aiter that │ │
│ │ does not implement anext: coroutine")>) │ │
│ │ task = <Task finished name='Task-4' coro=<start..run() done, defined at │ │
│ │ C:\Python312\Lib\site-packages\meilisync\main.py:169> │ │
│ │ exception=TypeError("'async for' received an object from aiter that │ │
│ │ does not implement anext: coroutine")> │ │
│ └──────────────────────────────────────────────────────────────────────────────────────────────┘ │
│ │
│ C:\Python312\Lib\asyncio\base_events.py:684 in run_until_complete │
│ │
│ 681 │ │ if not future.done(): │
│ 682 │ │ │ raise RuntimeError('Event loop stopped before Future completed.') │
│ 683 │ │ │
│ > 684 │ │ return future.result() │
│ 685 │ │
│ 686 │ def stop(self): │
│ 687 │ │ """Stop running the event loop. │
│ │
│ ┌─────────────────────────────────────────── locals ───────────────────────────────────────────┐ │
│ │ future = <Task finished name='Task-4' coro=<start..run() done, defined at │ │
│ │ C:\Python312\Lib\site-packages\meilisync\main.py:169> exception=TypeError("'async │ │
│ │ for' received an object from aiter that does not implement anext: │ │
│ │ coroutine")> │ │
│ │ new_task = False │ │
│ │ self = │ │
│ └──────────────────────────────────────────────────────────────────────────────────────────────┘ │
│ │
│ C:\Python312\Lib\site-packages\meilisync\main.py:172 in run │
│ │
│ 169 │ async def run(): │
│ 170 │ │ nonlocal lock │
│ 171 │ │ lock = asyncio.Lock() │
│ > 172 │ │ await asyncio.gather(
(), interval()) │
│ 173 │ │
│ 174 │ asyncio.run(run()) │
│ 175 │
│ │
│ ┌──────────────────────────────── locals ─────────────────────────────────┐ │
│ │ _ = <function start..
at 0x0000020673F679C0> │ │
│ │ interval = <function start..interval at 0x0000020673F67BA0> │ │
│ │ lock = <asyncio.locks.Lock object at 0x0000020673F6EDB0 [unlocked]> │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ C:\Python312\Lib\site-packages\meilisync\main.py:135 in _ │
│ │
│ 132 │ │ │ │ │ │ f'No data found for table "{settings.source.database}.{sync.tabl │
│ 133 │ │ │ │ │ ) │
│ 134 │ │ logger.info(f'Start increment sync data from "{settings.source.type}" to MeiliSe │
│ > 135 │ │ async for event in source: │
│ 136 │ │ │ if settings.debug: │
│ 137 │ │ │ │ logger.debug(event) │
│ 138 │ │ │ current_progress = event.progress │
│ │
│ ┌─────────────────────────────────────────── locals ───────────────────────────────────────────┐ │
│ │ collection = <meilisync.event.EventCollection object at 0x00000206739D0260> │ │
│ │ current_progress = {'start_lsn': '0/EE4E258'} │ │
│ │ lock = <asyncio.locks.Lock object at 0x0000020673F6EDB0 [unlocked]> │ │
│ │ meili = <meilisync.meili.Meili object at 0x00000206735B7F80> │ │
│ │ meili_settings = MeiliSearch( │ │
│ │ │ api_url='http://localhost:7700/', │ │
│ │ │ api_key='API KEY', │ │
│ │ │ insert_size=1000, │ │
│ │ │ insert_interval=10 │ │
│ │ ) │ │
│ │ progress = <meilisync.progress.file.File object at 0x00000206738EF260> │ │
│ │ settings = Settings( │ │
│ │ │ plugins=[], │ │
│ │ │ progress=Progress( │ │
│ │ │ │ type=<ProgressType.file: 'file'>, │ │
│ │ │ │ │ │
│ │ path='C:\\Python312\\Lib\\site-packages\\meilisync\\progress.j… │ │
│ │ │ ), │ │
│ │ │ debug=True, │ │
│ │ │ source=Source( │ │
│ │ │ │ type=<SourceType.postgres: 'postgres'>, │ │
│ │ │ │ database='DATABASE NAME', │ │
│ │ │ │ host='127.0.0.1', │ │
│ │ │ │ port=5432, │ │
│ │ │ │ user='postgres', │ │
│ │ │ │ password='root' │ │
│ │ │ ), │ │
│ │ │ meilisearch=MeiliSearch( │ │
│ │ │ │ api_url='http://localhost:7700/', │ │
│ │ │ │ api_key='API KEY', │ │
│ │ │ │ insert_size=1000, │ │
│ │ │ │ insert_interval=10 │ │
│ │ │ ), │ │
│ │ │ sync=[ │ │
│ │ │ │ Sync( │ │
│ │ │ │ │ plugins=[], │ │
│ │ │ │ │ table='booking', │ │
│ │ │ │ │ pk='id', │ │
│ │ │ │ │ full=True, │ │
│ │ │ │ │ index='booking', │ │
│ │ │ │ │ fields=None │ │
│ │ │ │ ) │ │
│ │ │ ], │ │
│ │ │ sentry=None │ │
│ │ ) │ │
│ │ source = <meilisync.source.postgres_old.Postgres object at 0x00000206734A7DA0> │ │
│ │ sync = Sync( │ │
│ │ │ plugins=[], │ │
│ │ │ table='booking', │ │
│ │ │ pk='id', │ │
│ │ │ full=True, │ │
│ │ │ index='booking', │ │
│ │ │ fields=None │ │
│ │ ) │ │
│ └──────────────────────────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘
TypeError: 'async for' received an object from aiter that does not implement anext: coroutine

I wanted to provide a quick update regarding the recent issues we encountered. In light of the numerous errors and their perplexing nature, I decided to leverage Docker as a solution.

The transition to Docker has proven to be highly effective, and the application is now running smoothly without any hiccups. It appears that the challenges we faced were rooted in the operating environment, and Docker has provided a robust and reliable workaround.

I’m using Meilisync using docker compose and I have the same issue:

meilisync-1    | TypeError: 'async for' requires an object with __aiter__ method, got coroutine
meilisync-1 exited with code 0

Edit: looks like an issue with progress.path because when I commented-out the line the problem went away.

@bfontaine,
what do you mean by "Edit: looks like an issue with progress.path because when I commented-out the line the problem went away"
unfortunately, when i deploy the app on AWS i receive the same error, i try 2 methods:
1- Meilisearch and Meilisync were installed in 2 docker container
2- an EC2 was created by Meilisearch image, Meilisync installed by docker

i am stuck in the 2 methods by the error "TypeError: 'async for' requires an object with aiter method, got coroutine"

After deploying the app using two methods—utilizing Docker containers with Meilisearch and Meilisync installed separately, and creating an EC2 instance with Meilisearch image and Meilisync installed via Docker—we've hit the same roadblock. The error message we're grappling with is: "TypeError: 'async for' requires an object with aiter method, got coroutine."

@kansoadi I had a custom path in the config, and when I removed it the issue went away.

With this config I have the error:

progress:
  type: file
  path: myprogress.json
# ...

With this one I don’t:

progress:
  type: file
# ...

@bfontaine,
but path is required if the type is set to file (type: file or redis, if set to file, another option path is required.)

_meilisync_1  | ValidationError: 1 validation error for Settings
meilisync_1  | progress
meilisync_1  |   Field required [type=missing, input_value={'debug': True,
meilisync_1  | 'plugins'...ronment': 'production'}}, input_type=dict]
meilisync_1  |     For further information visit https://errors.pydantic.dev/2.5/v/missing_

Please try latest source code

Sure, The latest source code was used;
'
docker pull long2ice/meilisync
Using default tag: latest
latest: Pulling from long2ice/meilisync
Digest: sha256:0916df358ccdcfeebad4d8c946c46641d2bf72a220907cde220d963638759f69
Status: Image is up to date for long2ice/meilisync:latest
docker.io/long2ice/meilisync:latest
"

I can't re reproduce locally.

For refresh:

image

For start:

image

I do have the same problem with the latest image, but was able to launch meilisync with older version

i got something familiar to this error :(
exception=TypeError("'async for' requires an object with aiter method, got list")>
i just pull the image (latest)
plz HELP :)

I have the same issue when i run "meilisync refresh"
image
Plz Help

i saw another error when i was running "meilisearch check"
image
instead of using ret[0], i replace it with ret["count"] and it worked.

Hi, @kansoadi Have you resolved the issue? I have the same error
"TypeError: 'async for' requires an object with aiter method, got coroutine"
Config below

debug: true
plugins:
  - meilisync.plugin.Plugin
progress:
  type: file
source:
  type: postgres
  host: docker.for.mac.host.internal 
  port: 5433
  database: test
  user: postgres
  password: <password>
meilisearch:
  api_url: http://docker.for.mac.host.internal:7700
  api_key: <admin_key>
  insert_size: 1000
  insert_interval: 10
sync:
  - table: games
    index: games_index
    full: true
    fields:
      id: