mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Add inotify support
This commit is contained in:
		| @@ -165,6 +165,8 @@ PAPERLESS_PASSPHRASE="secret" | |||||||
| #PAPERLESS_CONVERT_DENSITY=300 | #PAPERLESS_CONVERT_DENSITY=300 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # (This setting is ignored on Linux where inotify is used instead of a | ||||||
|  | # polling loop.) | ||||||
| # The number of seconds that Paperless will wait between checking | # The number of seconds that Paperless will wait between checking | ||||||
| # PAPERLESS_CONSUMPTION_DIR.  If you tend to write documents to this directory | # PAPERLESS_CONSUMPTION_DIR.  If you tend to write documents to this directory | ||||||
| # rarely, you may want to use a higher value than the default (10). | # rarely, you may want to use a higher value than the default (10). | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ flake8==3.5.0 | |||||||
| fuzzywuzzy==0.15.0 | fuzzywuzzy==0.15.0 | ||||||
| gunicorn==19.7.1 | gunicorn==19.7.1 | ||||||
| idna==2.6 | idna==2.6 | ||||||
|  | inotify_simple==1.1.7; sys_platform == 'linux' | ||||||
| langdetect==1.0.7 | langdetect==1.0.7 | ||||||
| mccabe==0.6.1 | mccabe==0.6.1 | ||||||
| more-itertools==4.1.0 | more-itertools==4.1.0 | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| import datetime | import datetime | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
|  | import sys | ||||||
| import time | import time | ||||||
|  |  | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| @@ -9,6 +10,11 @@ from django.core.management.base import BaseCommand, CommandError | |||||||
| from ...consumer import Consumer, ConsumerError, make_dirs | from ...consumer import Consumer, ConsumerError, make_dirs | ||||||
| from ...mail import MailFetcher, MailFetcherError | from ...mail import MailFetcher, MailFetcherError | ||||||
|  |  | ||||||
|  | try: | ||||||
|  |     from inotify_simple import INotify, flags | ||||||
|  | except ImportError: | ||||||
|  |     pass | ||||||
|  |  | ||||||
|  |  | ||||||
| class Command(BaseCommand): | class Command(BaseCommand): | ||||||
|     """ |     """ | ||||||
| @@ -53,6 +59,11 @@ class Command(BaseCommand): | |||||||
|             action="store_true", |             action="store_true", | ||||||
|             help="Run only once." |             help="Run only once." | ||||||
|         ) |         ) | ||||||
|  |         parser.add_argument( | ||||||
|  |             "--no-inotify", | ||||||
|  |             action="store_true", | ||||||
|  |             help="Don't use inotify, even if it's available." | ||||||
|  |         ) | ||||||
|  |  | ||||||
|     def handle(self, *args, **options): |     def handle(self, *args, **options): | ||||||
|  |  | ||||||
| @@ -60,6 +71,8 @@ class Command(BaseCommand): | |||||||
|         directory = options["directory"] |         directory = options["directory"] | ||||||
|         loop_time = options["loop_time"] |         loop_time = options["loop_time"] | ||||||
|         mail_delta = options["mail_delta"] * 60 |         mail_delta = options["mail_delta"] * 60 | ||||||
|  |         use_inotify = (not options["no_inotify"] | ||||||
|  |                        and "inotify_simple" in sys.modules) | ||||||
|  |  | ||||||
|         try: |         try: | ||||||
|             self.file_consumer = Consumer(consume=directory) |             self.file_consumer = Consumer(consume=directory) | ||||||
| @@ -70,14 +83,20 @@ class Command(BaseCommand): | |||||||
|         make_dirs(self.ORIGINAL_DOCS, self.THUMB_DOCS) |         make_dirs(self.ORIGINAL_DOCS, self.THUMB_DOCS) | ||||||
|  |  | ||||||
|         logging.getLogger(__name__).info( |         logging.getLogger(__name__).info( | ||||||
|             "Starting document consumer at {}".format(directory) |             "Starting document consumer at {}{}".format( | ||||||
|  |                 directory, | ||||||
|  |                 " with inotify" if use_inotify else "" | ||||||
|  |             ) | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         if options["oneshot"]: |         if options["oneshot"]: | ||||||
|             self.loop_step(mail_delta) |             self.loop_step(mail_delta) | ||||||
|         else: |         else: | ||||||
|             try: |             try: | ||||||
|                 self.loop(loop_time, mail_delta) |                 if use_inotify: | ||||||
|  |                     self.loop_inotify(mail_delta) | ||||||
|  |                 else: | ||||||
|  |                     self.loop(loop_time, mail_delta) | ||||||
|             except KeyboardInterrupt: |             except KeyboardInterrupt: | ||||||
|                 print("Exiting") |                 print("Exiting") | ||||||
|  |  | ||||||
| @@ -101,3 +120,27 @@ class Command(BaseCommand): | |||||||
|             self.mail_fetcher.pull() |             self.mail_fetcher.pull() | ||||||
|  |  | ||||||
|         self.file_consumer.consume_new_files() |         self.file_consumer.consume_new_files() | ||||||
|  |  | ||||||
|  |     def loop_inotify(self, mail_delta): | ||||||
|  |         directory = self.file_consumer.consume | ||||||
|  |         inotify = INotify() | ||||||
|  |         inotify.add_watch(directory, flags.CLOSE_WRITE | flags.MOVED_TO) | ||||||
|  |  | ||||||
|  |         # Run initial mail fetch and consume all currently existing documents | ||||||
|  |         self.loop_step(mail_delta) | ||||||
|  |         next_mail_time = self.mail_fetcher.last_checked + mail_delta | ||||||
|  |  | ||||||
|  |         while True: | ||||||
|  |             # Consume documents until next_mail_time | ||||||
|  |             while True: | ||||||
|  |                 delta = next_mail_time - time.time() | ||||||
|  |                 if delta > 0: | ||||||
|  |                     for event in inotify.read(timeout=delta): | ||||||
|  |                         file = os.path.join(directory, event.name) | ||||||
|  |                         if os.path.isfile(file): | ||||||
|  |                             self.file_consumer.try_consume_file(file) | ||||||
|  |                 else: | ||||||
|  |                     break | ||||||
|  |  | ||||||
|  |             self.mail_fetcher.pull() | ||||||
|  |             next_mail_time = self.mail_fetcher.last_checked + mail_delta | ||||||
|   | |||||||
| @@ -246,6 +246,8 @@ SCRATCH_DIR = os.getenv("PAPERLESS_SCRATCH_DIR", "/tmp/paperless") | |||||||
| # This is where Paperless will look for PDFs to index | # This is where Paperless will look for PDFs to index | ||||||
| CONSUMPTION_DIR = os.getenv("PAPERLESS_CONSUMPTION_DIR") | CONSUMPTION_DIR = os.getenv("PAPERLESS_CONSUMPTION_DIR") | ||||||
|  |  | ||||||
|  | # (This setting is ignored on Linux where inotify is used instead of a | ||||||
|  | # polling loop.) | ||||||
| # The number of seconds that Paperless will wait between checking | # The number of seconds that Paperless will wait between checking | ||||||
| # CONSUMPTION_DIR.  If you tend to write documents to this directory very | # CONSUMPTION_DIR.  If you tend to write documents to this directory very | ||||||
| # slowly, you may want to use a higher value than the default. | # slowly, you may want to use a higher value than the default. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Erik Arvstedt
					Erik Arvstedt