meilisync icon indicating copy to clipboard operation
meilisync copied to clipboard

Crash when full: true

Open longfellowone opened this issue 8 months ago • 1 comments

Running meilisync with docker-compose. When starting the container with sync config set to full: true container crashes with the following error (also get this when running meilisync refresh). Syncing works when adding new data, just can't get the initial data to sync

My config looks like this

debug: true

progress:
  type: file
  path: /tmp/progress.json

source:
  type: postgres
  host: postgres
  port: 5432
  user: default
  password: default
  database: default
  sslmode: disable

meilisearch:
  api_url: http://meilisearch:7700
  api_key: default
  insert_size: 1000
  insert_interval: 10

sync:
  - table: products
    index: products
    full: true

The error

root@c0492212d7f7:/meilisync# meilisync refresh
2025-05-13 23:00:43.522 | DEBUG    | meilisync.main:_:36 - plugins=[] progress=Progress(type=<ProgressType.file: 'file'>, path='/tmp/progress.json') debug=True source=Source(type=<SourceType.postgres: 'postgres'>, database='default', host='postgres', port=5432, user='default', password='default', sslmode='disable') meilisearch=MeiliSearch(api_url='http://meilisearch:7700', api_key='default', insert_size=1000, insert_interval=10) sync=[Sync(plugins=[], table='products', pk='id', full=False, index='products', fields=None)] sentry=None
2025-05-13 23:00:43.725 | INFO     | meilisync.meili:refresh_data:52 - Waiting for update tmp index products_tmp settings to complete...
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /meilisync/meilisync/main.py:176 in refresh                                                      │
│                                                                                                  │
│   173 │   │   │   │   │   │   f'No data found for table "{settings.source.database}.{sync.tabl   │
│   174 │   │   │   │   │   )                                                                      │
│   175 │                                                                                          │
│ ❱ 176 │   asyncio.run(_())                                                                       │
│   177                                                                                            │
│   178                                                                                            │
│   179 @app.command(                                                                              │
│                                                                                                  │
│ ╭───────────────────────── locals ──────────────────────────╮                                    │
│ │       _ = <function refresh.<locals>._ at 0x7ffffabfe5c0> │                                    │
│ │ context = <click.core.Context object at 0x7ffffab6a600>   │                                    │
│ │    size = 10000                                           │                                    │
│ │   table = []                                              │                                    │
│ ╰───────────────────────────────────────────────────────────╯                                    │
│                                                                                                  │
│ /usr/local/lib/python3.12/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 refresh.<locals>._ at 0x7ffffaf69580> │                       │
│ │       runner = <asyncio.runners.Runner object at 0x7ffffdba80e0>       │                       │
│ ╰────────────────────────────────────────────────────────────────────────╯                       │
│                                                                                                  │
│ /usr/local/lib/python3.12/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 0x7ffffab54240>                             │ │
│ │           coro = <coroutine object refresh.<locals>._ at 0x7ffffaf69580>                     │ │
│ │           self = <asyncio.runners.Runner object at 0x7ffffdba80e0>                           │ │
│ │ sigint_handler = functools.partial(<bound method Runner._on_sigint of                        │ │
│ │                  <asyncio.runners.Runner object at 0x7ffffdba80e0>>, main_task=<Task         │ │
│ │                  finished name='Task-4' coro=<refresh.<locals>._() done, defined at          │ │
│ │                  /meilisync/meilisync/main.py:153> exception=TypeError("'async for' requires │ │
│ │                  an object with __aiter__ method, got coroutine")>)                          │ │
│ │           task = <Task finished name='Task-4' coro=<refresh.<locals>._() done, defined at    │ │
│ │                  /meilisync/meilisync/main.py:153> exception=TypeError("'async for' requires │ │
│ │                  an object with __aiter__ method, got coroutine")>                           │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /usr/local/lib/python3.12/asyncio/base_events.py:664 in run_until_complete                       │
│                                                                                                  │
│    661 │   │   if not future.done():                                                             │
│    662 │   │   │   raise RuntimeError('Event loop stopped before Future completed.')             │
│    663 │   │                                                                                     │
│ ❱  664 │   │   return future.result()                                                            │
│    665 │                                                                                         │
│    666 │   def stop(self):                                                                       │
│    667 │   │   """Stop running the event loop.                                                   │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │   future = <Task finished name='Task-4' coro=<refresh.<locals>._() done, defined at          │ │
│ │            /meilisync/meilisync/main.py:153> exception=TypeError("'async for' requires an    │ │
│ │            object with __aiter__ method, got coroutine")>                                    │ │
│ │ new_task = False                                                                             │ │
│ │     self = <_UnixSelectorEventLoop running=False closed=True debug=False>                    │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /meilisync/meilisync/main.py:162 in _                                                            │
│                                                                                                  │
│   159 │   │   │   if not table or sync.table in table:                                           │
│   160 │   │   │   │   current_progress = await source.get_current_progress()                     │
│   161 │   │   │   │   await progress.set(**current_progress)                                     │
│ ❱ 162 │   │   │   │   count = await meili.refresh_data(                                          │
│   163 │   │   │   │   │   sync,                                                                  │
│   164 │   │   │   │   │   source.get_full_data(sync, size),                                      │
│   165 │   │   │   │   )                                                                          │
│                                                                                                  │
│ ╭───────────────────────────────────── locals ─────────────────────────────────────╮             │
│ │          context = <click.core.Context object at 0x7ffffab6a600>                 │             │
│ │ current_progress = {'start_lsn': '0/1A3A680'}                                    │             │
│ │            meili = <meilisync.meili.Meili object at 0x7ffffab07830>              │             │
│ │         progress = <meilisync.progress.file.File object at 0x7ffffc329370>       │             │
│ │         settings = Settings(                                                     │             │
│ │                    │   plugins=[],                                               │             │
│ │                    │   progress=Progress(                                        │             │
│ │                    │   │   type=<ProgressType.file: 'file'>,                     │             │
│ │                    │   │   path='/tmp/progress.json'                             │             │
│ │                    │   ),                                                        │             │
│ │                    │   debug=True,                                               │             │
│ │                    │   source=Source(                                            │             │
│ │                    │   │   type=<SourceType.postgres: 'postgres'>,               │             │
│ │                    │   │   database='default',                                   │             │
│ │                    │   │   host='postgres',                                      │             │
│ │                    │   │   port=5432,                                            │             │
│ │                    │   │   user='default',                                       │             │
│ │                    │   │   password='default',                                   │             │
│ │                    │   │   sslmode='disable'                                     │             │
│ │                    │   ),                                                        │             │
│ │                    │   meilisearch=MeiliSearch(                                  │             │
│ │                    │   │   api_url='http://meilisearch:7700',                    │             │
│ │                    │   │   api_key='default',                                    │             │
│ │                    │   │   insert_size=1000,                                     │             │
│ │                    │   │   insert_interval=10                                    │             │
│ │                    │   ),                                                        │             │
│ │                    │   sync=[                                                    │             │
│ │                    │   │   Sync(                                                 │             │
│ │                    │   │   │   plugins=[],                                       │             │
│ │                    │   │   │   table='products',                                 │             │
│ │                    │   │   │   pk='id',                                          │             │
│ │                    │   │   │   full=False,                                       │             │
│ │                    │   │   │   index='products_tmp',                             │             │
│ │                    │   │   │   fields=None                                       │             │
│ │                    │   │   )                                                     │             │
│ │                    │   ],                                                        │             │
│ │                    │   sentry=None                                               │             │
│ │                    )                                                             │             │
│ │             size = 10000                                                         │             │
│ │           source = <meilisync.source.postgres.Postgres object at 0x7ffffaba3380> │             │
│ │             sync = Sync(                                                         │             │
│ │                    │   plugins=[],                                               │             │
│ │                    │   table='products',                                         │             │
│ │                    │   pk='id',                                                  │             │
│ │                    │   full=False,                                               │             │
│ │                    │   index='products_tmp',                                     │             │
│ │                    │   fields=None                                               │             │
│ │                    )                                                             │             │
│ │            table = []                                                            │             │
│ ╰──────────────────────────────────────────────────────────────────────────────────╯             │
│                                                                                                  │
│ /meilisync/meilisync/meili.py:56 in refresh_data                                                 │
│                                                                                                  │
│    53 │   │   await self.client.wait_for_task(                                                   │
│    54 │   │   │   task_id=task.task_uid, timeout_in_ms=self.wait_for_task_timeout                │
│    55 │   │   )                                                                                  │
│ ❱  56 │   │   tasks, count = await self.add_full_data(sync, data)                                │
│    57 │   │   wait_tasks = [                                                                     │
│    58 │   │   │   self.client.wait_for_task(                                                     │
│    59 │   │   │   │   task_id=item.task_uid, timeout_in_ms=self.wait_for_task_timeout            │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │           data = <coroutine object Postgres.get_full_data at 0x7ffffa730d60>                 │ │
│ │          index = 'products'                                                                  │ │
│ │ index_name_tmp = 'products_tmp'                                                              │ │
│ │      index_tmp = AsyncIndex(uid='products_tmp', primary_key='id',                            │ │
│ │                  created_at=datetime.datetime(2025, 5, 13, 23, 0, 43, 659474),               │ │
│ │                  updated_at=datetime.datetime(2025, 5, 13, 23, 0, 43, 662568))               │ │
│ │             pk = 'id'                                                                        │ │
│ │           self = <meilisync.meili.Meili object at 0x7ffffab07830>                            │ │
│ │       settings = MeilisearchSettings(                                                        │ │
│ │                  │   synonyms={},                                                            │ │
│ │                  │   stop_words=[],                                                          │ │
│ │                  │   ranking_rules=[                                                         │ │
│ │                  │   │   'words',                                                            │ │
│ │                  │   │   'typo',                                                             │ │
│ │                  │   │   'proximity',                                                        │ │
│ │                  │   │   'attribute',                                                        │ │
│ │                  │   │   'sort',                                                             │ │
│ │                  │   │   'exactness'                                                         │ │
│ │                  │   ],                                                                      │ │
│ │                  │   filterable_attributes=[],                                               │ │
│ │                  │   distinct_attribute=None,                                                │ │
│ │                  │   searchable_attributes=['*'],                                            │ │
│ │                  │   displayed_attributes=['*'],                                             │ │
│ │                  │   sortable_attributes=[],                                                 │ │
│ │                  │   typo_tolerance=TypoTolerance(                                           │ │
│ │                  │   │   enabled=True,                                                       │ │
│ │                  │   │   disable_on_attributes=[],                                           │ │
│ │                  │   │   disable_on_words=[],                                                │ │
│ │                  │   │   min_word_size_for_typos=MinWordSizeForTypos(                        │ │
│ │                  │   │   │   one_typo=5,                                                     │ │
│ │                  │   │   │   two_typos=9                                                     │ │
│ │                  │   │   )                                                                   │ │
│ │                  │   ),                                                                      │ │
│ │                  │   faceting=Faceting(                                                      │ │
│ │                  │   │   max_values_per_facet=100,                                           │ │
│ │                  │   │   sort_facet_values_by={'*': 'alpha'}                                 │ │
│ │                  │   ),                                                                      │ │
│ │                  │   pagination=Pagination(max_total_hits=1000),                             │ │
│ │                  │   separator_tokens=[],                                                    │ │
│ │                  │   non_separator_tokens=[],                                                │ │
│ │                  │   dictionary=[]                                                           │ │
│ │                  )                                                                           │ │
│ │           sync = Sync(                                                                       │ │
│ │                  │   plugins=[],                                                             │ │
│ │                  │   table='products',                                                       │ │
│ │                  │   pk='id',                                                                │ │
│ │                  │   full=False,                                                             │ │
│ │                  │   index='products_tmp',                                                   │ │
│ │                  │   fields=None                                                             │ │
│ │                  )                                                                           │ │
│ │           task = TaskInfo(                                                                   │ │
│ │                  │   task_uid=3,                                                             │ │
│ │                  │   index_uid='products_tmp',                                               │ │
│ │                  │   status='enqueued',                                                      │ │
│ │                  │   task_type='settingsUpdate',                                             │ │
│ │                  │   enqueued_at=datetime.datetime(2025, 5, 13, 23, 0, 43, 722916)           │ │
│ │                  )                                                                           │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /meilisync/meilisync/meili.py:33 in add_full_data                                                │
│                                                                                                  │
│    30 │   async def add_full_data(self, sync: Sync, data: AsyncGenerator):                       │
│    31 │   │   tasks = []                                                                         │
│    32 │   │   count = 0                                                                          │
│ ❱  33 │   │   async for items in data:                                                           │
│    34 │   │   │   count += len(items)                                                            │
│    35 │   │   │   events = [Event(type=EventType.create, data=item) for item in items]           │
│    36 │   │   │   task = await self.handle_events_by_type(sync, events, EventType.create)        │
│                                                                                                  │
│ ╭────────────────────────────── locals ───────────────────────────────╮                          │
│ │ count = 0                                                           │                          │
│ │  data = <coroutine object Postgres.get_full_data at 0x7ffffa730d60> │                          │
│ │  self = <meilisync.meili.Meili object at 0x7ffffab07830>            │                          │
│ │  sync = Sync(                                                       │                          │
│ │         │   plugins=[],                                             │                          │
│ │         │   table='products',                                       │                          │
│ │         │   pk='id',                                                │                          │
│ │         │   full=False,                                             │                          │
│ │         │   index='products_tmp',                                   │                          │
│ │         │   fields=None                                             │                          │
│ │         )                                                           │                          │
│ │ tasks = []                                                          │                          │
│ ╰─────────────────────────────────────────────────────────────────────╯                          │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
TypeError: 'async for' requires an object with __aiter__ method, got coroutine
sys:1: RuntimeWarning: coroutine 'Postgres.get_full_data' was never awaited

longfellowone avatar May 13 '25 23:05 longfellowone

hey, in case you haven't fixed your problem yet i just want to say i had this same issue and have since fixed it.

in my docker compose file i didn't specify a tag, so it was pulling latest (actually from november 2023) changing the image to image: long2ice/meilisync:main fixed it and syncing now works

edit: changing to main does fix this, but it breaks sync too so Hooray!! check #121 for a forked repo that has fixes for both of the issues (in my limited testing)

lapaii avatar May 16 '25 19:05 lapaii