<commit_before>ASpellWorker = require "./ASpellWorker"
_ = require "underscore"
logger = require 'logger-sharelatex'
metrics = require('metrics-sharelatex')

class ASpellWorkerPool
	MAX_REQUESTS: 100*1024
	MAX_WORKERS: 32

	constructor: (@options) ->
		@PROCESS_POOL = []
		@timeout = 1000

	create: (language) ->
		if @PROCESS_POOL.length >= @MAX_WORKERS
			logger.log maxworkers: @MAX_WORKERS, "maximum number of workers already running"
			return null
		worker = new ASpellWorker(language, @options)
		worker.pipe.on 'exit', () =>
			logger.log process: worker.pipe.pid, lang: language, "removing aspell worker from pool"
			@cleanup()
		@PROCESS_POOL.push(worker)
		metrics.gauge 'aspellWorkerPool-size', @PROCESS_POOL.length
		return worker

	cleanup: () ->
		active = @PROCESS_POOL.filter (worker) ->
			worker.state != 'killed'
		@PROCESS_POOL = active
		metrics.gauge 'aspellWorkerPool-size', @PROCESS_POOL.length

	check: (language, words, timeout, callback) ->
		# look for an existing process in the pool
		availableWorker = _.find @PROCESS_POOL, (cached) ->
			cached.language == language && cached.isReady()
		if not availableWorker?
			worker = @create(language)
		else
			worker = availableWorker

		if not worker?
			# return error if too many workers
			callback(new Error("no worker available"))
			return

		if worker.idleTimer?
			clearTimeout worker.idleTimer
			worker.idleTimer = null

		killTimer = setTimeout () ->
			worker.pipe.kill('SIGKILL')
		, timeout || 1000

		worker.check words, (err, output) =>
			clearTimeout killTimer
			callback(err, output)
			# queue a shutdown if worker is not used
			if worker.count > @MAX_REQUESTS
				worker.shutdown("reached limit of " + @MAX_REQUESTS + " requests")
			else
				worker.idleTimer = setTimeout () ->
					worker.shutdown("idle worker")
					worker.idleTimer = null
				, 1000

module.exports = ASpellWorkerPool
<commit_msg>don't run the idle shutdown timer if the process has errored<commit_after>ASpellWorker = require "./ASpellWorker"
_ = require "underscore"
logger = require 'logger-sharelatex'
metrics = require('metrics-sharelatex')

class ASpellWorkerPool
	MAX_REQUESTS: 100*1024
	MAX_WORKERS: 32

	constructor: (@options) ->
		@PROCESS_POOL = []
		@timeout = 1000

	create: (language) ->
		if @PROCESS_POOL.length >= @MAX_WORKERS
			logger.log maxworkers: @MAX_WORKERS, "maximum number of workers already running"
			return null
		worker = new ASpellWorker(language, @options)
		worker.pipe.on 'exit', () =>
			logger.log process: worker.pipe.pid, lang: language, "removing aspell worker from pool"
			@cleanup()
		@PROCESS_POOL.push(worker)
		metrics.gauge 'aspellWorkerPool-size', @PROCESS_POOL.length
		return worker

	cleanup: () ->
		active = @PROCESS_POOL.filter (worker) ->
			worker.state != 'killed'
		@PROCESS_POOL = active
		metrics.gauge 'aspellWorkerPool-size', @PROCESS_POOL.length

	check: (language, words, timeout, callback) ->
		# look for an existing process in the pool
		availableWorker = _.find @PROCESS_POOL, (cached) ->
			cached.language == language && cached.isReady()
		if not availableWorker?
			worker = @create(language)
		else
			worker = availableWorker

		if not worker?
			# return error if too many workers
			callback(new Error("no worker available"))
			return

		if worker.idleTimer?
			clearTimeout worker.idleTimer
			worker.idleTimer = null

		killTimer = setTimeout () ->
			worker.pipe.kill('SIGKILL')
		, timeout || 1000

		worker.check words, (err, output) =>
			clearTimeout killTimer
			callback(err, output)
			return if err? # process has shut down
			if worker.count > @MAX_REQUESTS
				worker.shutdown("reached limit of " + @MAX_REQUESTS + " requests")
			else
				# queue a shutdown if worker is idle
				worker.idleTimer = setTimeout () ->
					worker.shutdown("idle worker")
					worker.idleTimer = null
				, 1000

module.exports = ASpellWorkerPool

{'fraction_non_alphanumeric': 0.11022610483042138, 'fraction_numerical': 0.01079136690647482, 'mean_word_length': 3.927848101265823, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2554823', 'n_tokens_mistral': 1417, 'n_tokens_neox': 1216, 'n_words': 332}