Comments (9)
Hi @AlexVelezLl - to avoid the issues you're seeing it might be simpler to artificially restrict the space available by setting this option: https://github.com/learningequality/kolibri/blob/develop/kolibri/utils/options.py#L659
If you set it to close to (or even exceeding) your regular drive's free space, it will restrict the space available for imports, but not impact the space available for the SQLite DB.
To update this, you can either edit the options.ini
file in your KOLIBRI_HOME folder, or you can set it temporarily using the KOLIBRI_MINIMUM_DISK_SPACE
environment variable. It accepts B, KB, MB, GB, TB, and PB - as it uses the logic in this module: https://github.com/learningequality/kolibri/blob/develop/kolibri/utils/data.py#L4
from kolibri.
The other thing I think we'd need to consider is the fact this is a syncable model, so I'd need to get a double check on how this might impact syncing!
from kolibri.
Hi @rtibbles! I have been trying to replicate the use case by mounting device with 20MB of free space and running kolibri with KOLIBRI_HOME="/mnt/test/.kolibri" yarn devserver
, and doing a full import of a facility with 1k+ lessons and 4k+ quizzes. But I havent been able to replicate the InsufficientStorage exception, but instead I get a sqlite3.OperationalError: disk I/O error
when the device runs out of space.
[python-devserver] DEBUG 2024-04-15 11:03:42,155 http://192.168.112.1:8080 "GET /api/morango/v1/buffers/?limit=200&offset=2400&transfer_session_id=318c8078009d4263b6403221f7b46f98 HTTP/1.1" 200 2739098
[python-devserver] DEBUG 2024-04-15 11:03:42,238 http://192.168.112.1:8080 "PATCH /api/morango/v1/transfersessions/318c8078009d4263b6403221f7b46f98/ HTTP/1.1" 200 604
[python-devserver] DEBUG 2024-04-15 11:03:42,240 [morango:pull] NetworkSessionContext -> NetworkPullTransferOperation = pending
[python-devserver] INFO 2024-04-15 11:03:42,240 Receiving data (2600/8034, 10.11MB)
[python-devserver] --- Logging error ---
[python-devserver] Traceback (most recent call last):
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context
[python-devserver] self.dialect.do_execute(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 736, in do_execute
[python-devserver] cursor.execute(statement, parameters)
[python-devserver] sqlite3.OperationalError: disk I/O error
[python-devserver]
[python-devserver] The above exception was the direct cause of the following exception:
[python-devserver]
[python-devserver] Traceback (most recent call last):
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/syncsession.py", line 667, in run
[python-devserver] self.proceed_to_and_wait_for(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/syncsession.py", line 628, in proceed_to_and_wait_for
[python-devserver] result = self.controller.proceed_to_and_wait_for(stage, callback=callback)
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/controller.py", line 224, in proceed_to_and_wait_for
[python-devserver] callback()
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/utils.py", line 192, in fire
[python-devserver] handler(**fire_kwargs)
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/utils.py", line 192, in fire
[python-devserver] handler(**fire_kwargs)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/auth/management/utils.py", line 700, in handler
[python-devserver] self.update_progress(
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/utils.py", line 314, in update_progress
[python-devserver] self.job.update_progress(new_progress, self.job.total_progress)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/job.py", line 258, in update_progress
[python-devserver] self.storage.update_job_progress(self.job_id, progress, total_progress)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 506, in update_job_progress
[python-devserver] self._update_job(job_id, progress=progress, total_progress=total_progress)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 657, in _update_job
[python-devserver] job, orm_job = self._get_job_and_orm_job(job_id, session)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 693, in _get_job_and_orm_job
[python-devserver] orm_job = session.query(ORMJob).filter_by(id=job_id).one_or_none()
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/query.py", line 2850, in one_or_none
[python-devserver] return self._iter().one_or_none()
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/query.py", line 2916, in _iter
[python-devserver] result = self.session.execute(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 1717, in execute
[python-devserver] result = conn._execute_20(statement, params or {}, execution_options)
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1710, in _execute_20
[python-devserver] return meth(self, args_10style, kwargs_10style, execution_options)
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/sql/elements.py", line 334, in _execute_on_connection
[python-devserver] return connection._execute_clauseelement(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1577, in _execute_clauseelement
[python-devserver] ret = self._execute_context(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1953, in _execute_context
[python-devserver] self._handle_dbapi_exception(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 2134, in _handle_dbapi_exception
[python-devserver] util.raise_(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 211, in raise_
[python-devserver] raise exception
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context
[python-devserver] self.dialect.do_execute(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 736, in do_execute
[python-devserver] cursor.execute(statement, parameters)
[python-devserver] sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) disk I/O error
[python-devserver] [SQL: SELECT jobs.id AS jobs_id, jobs.state AS jobs_state, jobs.func AS jobs_func, jobs.priority AS jobs_priority, jobs.queue AS jobs_queue, jobs.saved_job AS jobs_saved_job, jobs.time_created AS jobs_time_created, jobs.time_updated AS jobs_time_updated, jobs.interval AS jobs_interval, jobs.retry_interval AS jobs_retry_interval, jobs.repeat AS jobs_repeat, jobs.scheduled_time AS jobs_scheduled_time, jobs.worker_host AS jobs_worker_host, jobs.worker_process AS jobs_worker_process, jobs.worker_thread AS jobs_worker_thread, jobs.worker_extra AS jobs_worker_extra
[python-devserver] FROM jobs
[python-devserver] WHERE jobs.id = ?]
[python-devserver] [parameters: ('398a66d2fa024b139b48d705718d2f8f',)]
[python-devserver] (Background on this error at: https://sqlalche.me/e/14/e3q8)
[python-devserver]
[python-devserver] During handling of the above exception, another exception occurred:
[python-devserver]
[python-devserver] Traceback (most recent call last):
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context
[python-devserver] self.dialect.do_execute(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 736, in do_execute
[python-devserver] cursor.execute(statement, parameters)
[python-devserver] sqlite3.OperationalError: disk I/O error
[python-devserver]
[python-devserver] The above exception was the direct cause of the following exception:
[python-devserver]
[python-devserver] Traceback (most recent call last):
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/job.py", line 329, in execute
[python-devserver] result = func(*args, **kwargs)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/registry.py", line 238, in __call__
[python-devserver] return self.func(*args, **kwargs)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/auth/tasks.py", line 393, in peerfacilityimport
[python-devserver] call_command(command, **kwargs)
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/django/core/management/__init__.py", line 131, in call_command
[python-devserver] return command.execute(*args, **defaults)
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/django/core/management/base.py", line 330, in execute
[python-devserver] output = self.handle(*args, **options)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/management/commands/base.py", line 28, in handle
[python-devserver] return self.handle_async(*args, **options)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/auth/management/commands/sync.py", line 180, in handle_async
[python-devserver] self._sync(sync_session_client, **options)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/auth/management/utils.py", line 437, in _sync
[python-devserver] self._pull(
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/auth/management/utils.py", line 567, in _pull
[python-devserver] sync_client.run()
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/syncsession.py", line 667, in run
[python-devserver] self.proceed_to_and_wait_for(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/utils.py", line 232, in __exit__
[python-devserver] self.completed.fire()
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/utils.py", line 192, in fire
[python-devserver] handler(**fire_kwargs)
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/utils.py", line 192, in fire
[python-devserver] handler(**fire_kwargs)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/auth/management/utils.py", line 700, in handler
[python-devserver] self.update_progress(
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/utils.py", line 314, in update_progress
[python-devserver] self.job.update_progress(new_progress, self.job.total_progress)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/job.py", line 258, in update_progress
[python-devserver] self.storage.update_job_progress(self.job_id, progress, total_progress)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 506, in update_job_progress
[python-devserver] self._update_job(job_id, progress=progress, total_progress=total_progress)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 657, in _update_job
[python-devserver] job, orm_job = self._get_job_and_orm_job(job_id, session)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 693, in _get_job_and_orm_job
[python-devserver] orm_job = session.query(ORMJob).filter_by(id=job_id).one_or_none()
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/query.py", line 2850, in one_or_none
[python-devserver] return self._iter().one_or_none()
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/query.py", line 2916, in _iter
[python-devserver] result = self.session.execute(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 1717, in execute
[python-devserver] result = conn._execute_20(statement, params or {}, execution_options)
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1710, in _execute_20
[python-devserver] return meth(self, args_10style, kwargs_10style, execution_options)
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/sql/elements.py", line 334, in _execute_on_connection
[python-devserver] return connection._execute_clauseelement(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1577, in _execute_clauseelement
[python-devserver] ret = self._execute_context(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1953, in _execute_context
[python-devserver] self._handle_dbapi_exception(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 2134, in _handle_dbapi_exception
[python-devserver] util.raise_(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 211, in raise_
[python-devserver] raise exception
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context
[python-devserver] self.dialect.do_execute(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 736, in do_execute
[python-devserver] cursor.execute(statement, parameters)
[python-devserver] sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) disk I/O error
[python-devserver] [SQL: SELECT jobs.id AS jobs_id, jobs.state AS jobs_state, jobs.func AS jobs_func, jobs.priority AS jobs_priority, jobs.queue AS jobs_queue, jobs.saved_job AS jobs_saved_job, jobs.time_created AS jobs_time_created, jobs.time_updated AS jobs_time_updated, jobs.interval AS jobs_interval, jobs.retry_interval AS jobs_retry_interval, jobs.repeat AS jobs_repeat, jobs.scheduled_time AS jobs_scheduled_time, jobs.worker_host AS jobs_worker_host, jobs.worker_process AS jobs_worker_process, jobs.worker_thread AS jobs_worker_thread, jobs.worker_extra AS jobs_worker_extra
[python-devserver] FROM jobs
[python-devserver] WHERE jobs.id = ?]
[python-devserver] [parameters: ('398a66d2fa024b139b48d705718d2f8f',)]
[python-devserver] (Background on this error at: https://sqlalche.me/e/14/e3q8)
[python-devserver]
[python-devserver] During handling of the above exception, another exception occurred:
[python-devserver]
[python-devserver] Traceback (most recent call last):
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/lib/python3.9/logging/__init__.py", line 1086, in emit
[python-devserver] stream.write(msg + self.terminator)
[python-devserver] OSError: [Errno 28] No space left on device
[python-devserver] Call stack:
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/lib/python3.9/threading.py", line 937, in _bootstrap
[python-devserver] self._bootstrap_inner()
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/lib/python3.9/threading.py", line 980, in _bootstrap_inner
[python-devserver] self.run()
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/lib/python3.9/threading.py", line 917, in run
[python-devserver] self._target(*self._args, **self._kwargs)
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/lib/python3.9/concurrent/futures/thread.py", line 83, in _worker
[python-devserver] work_item.run()
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/lib/python3.9/concurrent/futures/thread.py", line 58, in run
[python-devserver] result = self.fn(*self.args, **self.kwargs)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/worker.py", line 55, in execute_job_with_python_worker
[python-devserver] execute_job(
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/worker.py", line 31, in execute_job
[python-devserver] job.execute()
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/job.py", line 337, in execute
[python-devserver] logger.error(
[python-devserver] Message: 'Job 398a66d2fa024b139b48d705718d2f8f raised an exception: Traceback (most recent call last):\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context\n self.dialect.do_execute(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 736, in do_execute\n cursor.execute(statement, parameters)\nsqlite3.OperationalError: disk I/O error\n\nThe above exception was the direct cause of the following exception:\n\nTraceback (most recent call last):\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/syncsession.py", line 667, in run\n self.proceed_to_and_wait_for(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/syncsession.py", line 628, in proceed_to_and_wait_for\n result = self.controller.proceed_to_and_wait_for(stage, callback=callback)\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/controller.py", line 224, in proceed_to_and_wait_for\n callback()\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/utils.py", line 192, in fire\n handler(**fire_kwargs)\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/utils.py", line 192, in fire\n handler(**fire_kwargs)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/auth/management/utils.py", line 700, in handler\n self.update_progress(\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/utils.py", line 314, in update_progress\n self.job.update_progress(new_progress, self.job.total_progress)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/job.py", line 258, in update_progress\n self.storage.update_job_progress(self.job_id, progress, total_progress)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 506, in update_job_progress\n self._update_job(job_id, progress=progress, total_progress=total_progress)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 657, in _update_job\n job, orm_job = self._get_job_and_orm_job(job_id, session)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 693, in _get_job_and_orm_job\n orm_job = session.query(ORMJob).filter_by(id=job_id).one_or_none()\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/query.py", line 2850, in one_or_none\n return self._iter().one_or_none()\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/query.py", line 2916, in _iter\n result = self.session.execute(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 1717, in execute\n result = conn._execute_20(statement, params or {}, execution_options)\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1710, in _execute_20\n return meth(self, args_10style, kwargs_10style, execution_options)\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/sql/elements.py", line 334, in _execute_on_connection\n return connection._execute_clauseelement(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1577, in _execute_clauseelement\n ret = self._execute_context(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1953, in _execute_context\n self._handle_dbapi_exception(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 2134, in _handle_dbapi_exception\n util.raise_(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 211, in raise_\n raise exception\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context\n self.dialect.do_execute(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 736, in do_execute\n cursor.execute(statement, parameters)\nsqlalchemy.exc.OperationalError: (sqlite3.OperationalError) disk I/O error\n[SQL: SELECT jobs.id AS jobs_id, jobs.state AS jobs_state, jobs.func AS jobs_func, jobs.priority AS jobs_priority, jobs.queue AS jobs_queue, jobs.saved_job AS jobs_saved_job, jobs.time_created AS jobs_time_created, jobs.time_updated AS jobs_time_updated, jobs.interval AS jobs_interval, jobs.retry_interval AS jobs_retry_interval, jobs.repeat AS jobs_repeat, jobs.scheduled_time AS jobs_scheduled_time, jobs.worker_host AS jobs_worker_host, jobs.worker_process AS jobs_worker_process, jobs.worker_thread AS jobs_worker_thread, jobs.worker_extra AS jobs_worker_extra \nFROM jobs \nWHERE jobs.id = ?]\n[parameters: (\'398a66d2fa024b139b48d705718d2f8f\',)]\n(Background on this error at: https://sqlalche.me/e/14/e3q8)\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context\n self.dialect.do_execute(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 736, in do_execute\n cursor.execute(statement, parameters)\nsqlite3.OperationalError: disk I/O error\n\nThe above exception was the direct cause of the following exception:\n\nTraceback (most recent call last):\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/job.py", line 329, in execute\n result = func(*args, **kwargs)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/registry.py", line 238, in __call__\n return self.func(*args, **kwargs)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/auth/tasks.py", line 393, in peerfacilityimport\n call_command(command, **kwargs)\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/django/core/management/__init__.py", line 131, in call_command\n return command.execute(*args, **defaults)\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/django/core/management/base.py", line 330, in execute\n output = self.handle(*args, **options)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/management/commands/base.py", line 28, in handle\n return self.handle_async(*args, **options)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/auth/management/commands/sync.py", line 180, in handle_async\n self._sync(sync_session_client, **options)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/auth/management/utils.py", line 437, in _sync\n self._pull(\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/auth/management/utils.py", line 567, in _pull\n sync_client.run()\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/syncsession.py", line 667, in run\n self.proceed_to_and_wait_for(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/utils.py", line 232, in __exit__\n self.completed.fire()\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/utils.py", line 192, in fire\n handler(**fire_kwargs)\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/utils.py", line 192, in fire\n handler(**fire_kwargs)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/auth/management/utils.py", line 700, in handler\n self.update_progress(\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/utils.py", line 314, in update_progress\n self.job.update_progress(new_progress, self.job.total_progress)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/job.py", line 258, in update_progress\n self.storage.update_job_progress(self.job_id, progress, total_progress)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 506, in update_job_progress\n self._update_job(job_id, progress=progress, total_progress=total_progress)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 657, in _update_job\n job, orm_job = self._get_job_and_orm_job(job_id, session)\n File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 693, in _get_job_and_orm_job\n orm_job = session.query(ORMJob).filter_by(id=job_id).one_or_none()\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/query.py", line 2850, in one_or_none\n return self._iter().one_or_none()\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/query.py", line 2916, in _iter\n result = self.session.execute(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 1717, in execute\n result = conn._execute_20(statement, params or {}, execution_options)\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1710, in _execute_20\n return meth(self, args_10style, kwargs_10style, execution_options)\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/sql/elements.py", line 334, in _execute_on_connection\n return connection._execute_clauseelement(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1577, in _execute_clauseelement\n ret = self._execute_context(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1953, in _execute_context\n self._handle_dbapi_exception(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 2134, in _handle_dbapi_exception\n util.raise_(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 211, in raise_\n raise exception\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context\n self.dialect.do_execute(\n File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 736, in do_execute\n cursor.execute(statement, parameters)\nsqlalchemy.exc.OperationalError: (sqlite3.OperationalError) disk I/O error\n[SQL: SELECT jobs.id AS jobs_id, jobs.state AS jobs_state, jobs.func AS jobs_func, jobs.priority AS jobs_priority, jobs.queue AS jobs_queue, jobs.saved_job AS jobs_saved_job, jobs.time_created AS jobs_time_created, jobs.time_updated AS jobs_time_updated, jobs.interval AS jobs_interval, jobs.retry_interval AS jobs_retry_interval, jobs.repeat AS jobs_repeat, jobs.scheduled_time AS jobs_scheduled_time, jobs.worker_host AS jobs_worker_host, jobs.worker_process AS jobs_worker_process, jobs.worker_thread AS jobs_worker_thread, jobs.worker_extra AS jobs_worker_extra \nFROM jobs \nWHERE jobs.id = ?]\n[parameters: (\'398a66d2fa024b139b48d705718d2f8f\',)]\n(Background on this error at: https://sqlalche.me/e/14/e3q8)\n'
[python-devserver] Arguments: ()
[python-devserver] ERROR 2024-04-15 11:03:42,247 Job 398a66d2fa024b139b48d705718d2f8f raised an exception: Traceback (most recent call last):
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context
[python-devserver] self.dialect.do_execute(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 736, in do_execute
[python-devserver] cursor.execute(statement, parameters)
[python-devserver] sqlite3.OperationalError: disk I/O error
[python-devserver]
[python-devserver] The above exception was the direct cause of the following exception:
[python-devserver]
[python-devserver] Traceback (most recent call last):
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/syncsession.py", line 667, in run
[python-devserver] self.proceed_to_and_wait_for(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/syncsession.py", line 628, in proceed_to_and_wait_for
[python-devserver] result = self.controller.proceed_to_and_wait_for(stage, callback=callback)
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/controller.py", line 224, in proceed_to_and_wait_for
[python-devserver] callback()
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/utils.py", line 192, in fire
[python-devserver] handler(**fire_kwargs)
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/morango/sync/utils.py", line 192, in fire
[python-devserver] handler(**fire_kwargs)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/auth/management/utils.py", line 700, in handler
[python-devserver] self.update_progress(
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/utils.py", line 314, in update_progress
[python-devserver] self.job.update_progress(new_progress, self.job.total_progress)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/job.py", line 258, in update_progress
[python-devserver] self.storage.update_job_progress(self.job_id, progress, total_progress)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 506, in update_job_progress
[python-devserver] self._update_job(job_id, progress=progress, total_progress=total_progress)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 657, in _update_job
[python-devserver] job, orm_job = self._get_job_and_orm_job(job_id, session)
[python-devserver] File "/home/alexvelezll/Documents/jobs/learningequality/repos/kolibri/kolibri/core/tasks/storage.py", line 693, in _get_job_and_orm_job
[python-devserver] orm_job = session.query(ORMJob).filter_by(id=job_id).one_or_none()
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/query.py", line 2850, in one_or_none
[python-devserver] return self._iter().one_or_none()
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/query.py", line 2916, in _iter
[python-devserver] result = self.session.execute(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 1717, in execute
[python-devserver] result = conn._execute_20(statement, params or {}, execution_options)
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1710, in _execute_20
[python-devserver] return meth(self, args_10style, kwargs_10style, execution_options)
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/sql/elements.py", line 334, in _execute_on_connection
[python-devserver] return connection._execute_clauseelement(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1577, in _execute_clauseelement
[python-devserver] ret = self._execute_context(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1953, in _execute_context
[python-devserver] self._handle_dbapi_exception(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 2134, in _handle_dbapi_exception
[python-devserver] util.raise_(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 211, in raise_
[python-devserver] raise exception
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context
[python-devserver] self.dialect.do_execute(
[python-devserver] File "/home/alexvelezll/.pyenv/versions/3.9.18/envs/kolibri-py3.9/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 736, in do_execute
[python-devserver] cursor.execute(statement, parameters)
[python-devserver] sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) disk I/O error
[python-devserver] [SQL: SELECT jobs.id AS jobs_id, jobs.state AS jobs_state, jobs.func AS jobs_func, jobs.priority AS jobs_priority, jobs.queue AS jobs_queue, jobs.saved_job AS jobs_saved_job, jobs.time_created AS jobs_time_created, jobs.time_updated AS jobs_time_updated, jobs.interval AS jobs_interval, jobs.retry_interval AS jobs_retry_interval, jobs.repeat AS jobs_repeat, jobs.scheduled_time AS jobs_scheduled_time, jobs.worker_host AS jobs_worker_host, jobs.worker_process AS jobs_worker_process, jobs.worker_thread AS jobs_worker_thread, jobs.worker_extra AS jobs_worker_extra
[python-devserver] FROM jobs
[python-devserver] WHERE jobs.id = ?]
[python-devserver] [parameters: ('398a66d2fa024b139b48d705718d2f8f',)]
[python-devserver] (Background on this error at: https://sqlalche.me/e/14/e3q8)
[python-devserver]
[python-devserver] During handling of the above exception, another exception occurred:
....
Meanwhile, the import progress just stops without any error message:
from kolibri.
@rtibbles The only way to run into this is that we have the same user with different Morango instanceID. That would be why update_or_create does not find a record, because the pair of (instance_id, user_id) would not be the same, and when trying to write the record, we would be writing a record with a repeated user_id, and that is why it would be violating the UNIQUE constraint of the user_id
field.
Could this happen when doing a full import of a facility that already had a record of the admin device in the device_learnerdevicestatus
table with the morango instanceID of one device, and then when trying to import to the other device?, the user id would be kept, but not the morango instanceID. I don't have two different devices to test this case, but I have manually changed the instanceId of morango and this way I have managed to replicate the error.
In any case, I think the solution could be to change the UNIQUE constraint to have both properties (instance_id, user_id), or remove the UNIQUE constraint from user_id
in the database and have this constraint handled from the application layer.
from kolibri.
OK, so as I understand it the issue is that the user field on the LearnerDeviceStatus model is set as OneToOneField
: https://github.com/learningequality/kolibri/blob/release-v0.16.x/kolibri/core/device/models.py#L613
Which enforces the constraint on both sides of the relationship, so if we have a LearnerDeviceStatus for multiple devices for the same learner, then we will have an issue.
So it seems that what we actually need is for it to be a ForeignKeyField
so that it is only enforced on one side.
However, this may have downstream effects on where this is referenced, so I think we would need to dig in more into where this is used to make sure this wouldn't cause additional issues (as it may have been referenced for lookups on the FacilityUser assuming it will only ever return a single status).
from kolibri.
However, this may have downstream effects on where this is referenced, so I think we would need to dig in more into where this is used to make sure this wouldn't cause additional issues
I have been searching the code for references to the LearnerDeviceStatus
model, and I have not found places where the query is done only with user_id
, but with both (user_id, instance_id), or by dataset_id. Within the model, the pair (instance_id, user_id) is also always taken into account, for example to delete the learner_status. Even in tests, it is always filtered by both fields. Other than those places, I haven't found any others where we refer to the LearnerDeviceStatus
model to query data.
And it seems that at one point an attempt was made to put a unique_together contraint on both fields
from kolibri.
OK, in that case loosening the OneToOneField to a ForeignKeyField seems appropriate.
Alternatively, if the intention is only to have a single LearnerDeviceStatus model per user, then we should be doing a different update.
from kolibri.
So, it seems that we want to change the OneToOneField to a ForeignKeyField.
To handle the backwards compatibility issue, we will need to add some special sauce to ensure that we do not try to sync multiple LearnerDeviceStatuses for a single user to a Kolibri device with a version less than 0.16.2.
There are three cases we need to consider:
-
a learner only device that has Kolibri less than 0.16.2 installed, syncing with a server that has 0.16.2 installed, but that has already synced to another learner only device where the same learner had been imported - so the server would have a LearnerDeviceStatus for a different LOD device that would then sync to the current LOD.
-
a learner only device that has Kolibri 0.16.2 installed, but has learner device statuses for itself, and for at least one other learner only device (this could have happened by syncing to with the 0.16.2 server in 1), syncing with a server with Kolibri less than 0.16.2 installed.
-
A full facility server with Kolibri 0.16.2 has multiple LearnerDeviceStatuses for the same learner, does a full facility sync with a Kolibri with a version less than 0.16.2
For each scenario we should do the following:
- Subclass https://github.com/learningequality/kolibri/blob/develop/kolibri/core/auth/sync_operations.py#L154 in the downgrade method check if a single user sync, and if so delete LearnerDeviceStatus objects for the user being synced that are not for the instance_id of the remote that is syncing.
- Subclass https://github.com/learningequality/kolibri/blob/develop/kolibri/core/auth/sync_operations.py#L154 in the downgrade method check if a single user sync, and if so delete LearnerDeviceStatus objects for the user being synced that are not for the instance_id of the local that is syncing.
- Subclass https://github.com/learningequality/kolibri/blob/develop/kolibri/core/auth/sync_operations.py#L154 in the downgrade method check if a single user sync, and if so delete LearnerDeviceStatus objects for the every user in the facility being synced that are not for the instance_id of the remote that is syncing.
I think all 3 can be implemented in the same subclass with some conditional logic.
For an example of how to register the operation to be used, see here: https://github.com/learningequality/kolibri/blob/develop/kolibri/core/logger/kolibri_plugin.py#L40
Would need to add register a new FacilityDataSyncHook subclass in here: https://github.com/learningequality/kolibri/blob/develop/kolibri/core/device/kolibri_plugin.py and set the operations as initializing_operations
from kolibri.
Closed with #12153
from kolibri.
Related Issues (20)
- Write helper function(s) to manage display of metadata tags following prioritization criteria
- Implement conditionalized and prioritized metadata label display on Channel card
- Implement conditionalized and prioritized metadata label display on Folder card
- Create MVP Coach "channel card" using `<KCard>` to use in the resource management side panel HOT 3
- Implement conditionalized and prioritized metadata label display on Resource card
- EQM - Add new section/Edit Section - The 'Section settings' modal remains open after clicking 'Delete section' HOT 3
- TypeError: Cannot read properties of null (reading 'demographic_fields') HOT 1
- make docker-whl (build error: incompatible engine node version)
- Attempt to access undefined AttemptLog when looking at reports HOT 1
- Update dropshadows to the latest Kolibri Design System guidelines HOT 6
- Remove hardcoded color used for the button hover state HOT 4
- Prevent sensitive information like user passwords from being logged/captured
- Move `avg_request_time_to_error` to the backend `context` HOT 1
- Remove core vuex channel fetching logic and state and move to coach
- Move core vuex state registration out of the core store
- Make 'notify_team_new_comment' GitHub action re-usable HOT 2
- Update 'notify_team_new_comment' GitHub action to ignore comments by the Sentry bot
- Migrate error codes into constants
- Spacing issues on coach resource count and icon on folders in RTL UI
- Remove FocusTrap in favor of KFocusTrap
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from kolibri.