batch_unpacker.py 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import os
  2. import json
  3. import socket
  4. import sys
  5. import time
  6. import tempfile
  7. from threading import Thread
  8. from subprocess import check_output
  9. from bookworm import s3, parse
  10. from bookworm.logger import log, setup_logger
  11. from bookworm.constants import UNPACKABLE_EXTENSIONS, REDIS
  12. import redis
  13. def should_unpack(fname):
  14. fname = fname.lower()
  15. return fname.endswith('rar') or fname.endswith('zip')
  16. def archive_contents(fd):
  17. to_extract = {}
  18. contents = check_output(['lsar', '-j', fd.name]).decode('utf-8')
  19. contents = json.loads(contents)
  20. log.debug(contents['lsarContents'])
  21. for f in contents['lsarContents']:
  22. fname = f['XADFileName']
  23. log.info('Found file %s in the archive', fname)
  24. if any([extension in fname.lower() for extension in ['.txt'] + UNPACKABLE_EXTENSIONS]):
  25. log.info('Extracting %s from the archive', fname)
  26. to_extract[f['XADIndex']] = fname
  27. return to_extract
  28. def delete_raw_file(s3client, s3key, meta):
  29. log.info('Deleting %s from %s', s3key, meta['raw_file_bucket'])
  30. s3client.delete_object(Bucket=meta['raw_file_bucket'], Key=s3key)
  31. def unpack_and_store(job_key, s3key, s3client, redis, meta):
  32. redis.hset(job_key, REDIS.STEP_KEY, 'UNPACKING')
  33. unpacked_files = unpack(s3key, s3client, redis, meta)
  34. redis.hset(job_key, REDIS.STEP_KEY, 'UNPACK_DONE')
  35. log.info('Done unpacking job %s', job_key)
  36. for fname, data in unpacked_files:
  37. log.info('Batch process file: %s', fname)
  38. try:
  39. decoded = data.decode('utf-8')
  40. except UnicodeDecodeError:
  41. decoded = data.decode('latin-1')
  42. books = parse.lines_to_dicts(decoded.replace('\r', '').splitlines())
  43. parse.insert_books(books)
  44. #delete_raw_file(s3client, s3key, meta)
  45. redis.delete(job_key)
  46. def unpack(s3key, s3client, redis, meta):
  47. log.info('Got a request to unpack %s', s3key)
  48. data = s3client.get_object(Key=s3key, Bucket=meta['raw_file_bucket'])
  49. with tempfile.NamedTemporaryFile() as fd:
  50. raw_file_contents = data['Body'].read()
  51. fd.write(raw_file_contents)
  52. fd.flush()
  53. if not should_unpack(s3key):
  54. log.info("Not unpacking %s", s3key)
  55. return [(s3key, raw_file_contents)]
  56. to_extract = archive_contents(fd)
  57. if not to_extract:
  58. log.error("Could not find any valid file")
  59. return []
  60. ret = []
  61. for index, fname in to_extract.items():
  62. log.info('Processing %s %s', index, fname)
  63. file_contents = check_output(['unar', '-o', '-', '-i', fd.name, str(index)])
  64. log.info('Got %d bytes', len(file_contents))
  65. ret.append((fname, file_contents))
  66. return ret
  67. def main():
  68. r = redis.StrictRedis(host='localhost', port=6379)
  69. setup_logger()
  70. s3client = s3.client()
  71. while True:
  72. log.info('Waiting for message on %s', REDIS.Q_PROCESS_BATCH_FILE)
  73. topic, message = r.blpop(REDIS.Q_PROCESS_BATCH_FILE)
  74. log.info('got message: %s', message)
  75. params = json.loads(message.decode('utf-8'))
  76. log.info('params for unpacker: %s', params)
  77. params['s3client'] = s3client
  78. params['redis'] = r
  79. t = Thread(target=unpack_and_store, kwargs=params)
  80. t.daemon = True
  81. t.start()