Skip to content

Commit 3910013

Browse files
Revert "feat(fts): Add comprehensive Full Text Search management to CWA Settings"
This reverts commit 8638224.
1 parent 6b4601f commit 3910013

8 files changed

Lines changed: 10 additions & 736 deletions

File tree

CONTRIBUTORS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ Copyright (C) 2024-2026 Calibre-Web Automated contributors
315315
- zhiyue (1 commits)
316316
# Fork Contributors (crocodilestick/calibre-web-automated)
317317

318-
- crocodilestick (989 commits)
318+
- crocodilestick (990 commits)
319319
- jmarmstrong1207 (73 commits)
320320
- demitrix (30 commits)
321321
- sirwolfgang (29 commits)

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ RUN \
284284
# Add unrar from unrar stage
285285
COPY --from=unrar /usr/bin/unrar-ubuntu /usr/bin/unrar
286286

287-
# Set calibre environment variables
287+
# Set calibre environment variable
288288
ENV CALIBRE_CONFIG_DIR=/config/.config/calibre
289289

290290
# Ports and volumes

cps/admin.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2164,7 +2164,6 @@ def _configuration_update_helper():
21642164
_config_checkbox_int(to_save, "config_uploading")
21652165
_config_checkbox_int(to_save, "config_unicode_filename")
21662166
_config_checkbox_int(to_save, "config_embed_metadata")
2167-
_config_checkbox(to_save, "config_fulltext_search")
21682167
# Reboot on config_anonbrowse with enabled ldap, as decoraters are changed in this case
21692168
reboot_required |= (_config_checkbox_int(to_save, "config_anonbrowse")
21702169
and config.config_login_type == constants.LOGIN_LDAP)
@@ -2310,19 +2309,10 @@ def _configuration_update_helper():
23102309
_configuration_result(_("Oops! Database Error: %(error)s.", error=e.orig))
23112310

23122311
config.save()
2313-
2314-
# Note: FTS initialization is now primarily managed via CWA Settings page
2315-
# This just provides basic validation
2316-
fts_warning = None
2317-
if config.config_fulltext_search and not config.config_calibre_dir:
2318-
fts_warning = _('Full Text Search enabled but no library path configured.')
2319-
23202312
if reboot_required:
23212313
web_server.stop(True)
23222314

2323-
# Combine all warnings
2324-
combined_warnings = " ".join(filter(None, [unrar_warning, arch_warning, fts_warning]))
2325-
return _configuration_result(None, reboot_required, combined_warnings if combined_warnings else None)
2315+
return _configuration_result(None, reboot_required, " ".join(filter(None, [unrar_warning, arch_warning])))
23262316

23272317

23282318
def _configuration_result(error_flash=None, reboot=False, warning_flash=None):

cps/config_sql.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@ class _Settings(_Base):
146146
config_upload_formats = Column(String, default=','.join(constants.EXTENSIONS_UPLOAD))
147147
config_unicode_filename = Column(Boolean, default=False)
148148
config_embed_metadata = Column(Boolean, default=True)
149-
config_fulltext_search = Column(Boolean, default=False)
150149

151150
config_updatechannel = Column(Integer, default=constants.UPDATE_STABLE)
152151

cps/cwa_functions.py

Lines changed: 0 additions & 286 deletions
Original file line numberDiff line numberDiff line change
@@ -711,8 +711,6 @@ def set_cwa_settings():
711711
int_value = max(500, min(50000, int_value))
712712
elif setting == 'duplicate_scan_debounce_seconds':
713713
int_value = max(5, min(600, int_value))
714-
elif setting == 'duplicate_auto_resolve_cooldown_minutes':
715-
int_value = max(0, min(1440, int_value)) # Clamp between 0 and 1440 minutes (24 hours)
716714
result[setting] = int_value
717715
except (ValueError, TypeError):
718716
# Use current value if conversion fails
@@ -726,8 +724,6 @@ def set_cwa_settings():
726724
result[setting] = cwa_db.cwa_settings.get(setting, 2) # Default to 2 AM
727725
elif setting == 'duplicate_scan_debounce_seconds':
728726
result[setting] = cwa_db.cwa_settings.get(setting, 30)
729-
elif setting == 'duplicate_auto_resolve_cooldown_minutes':
730-
result[setting] = cwa_db.cwa_settings.get(setting, 0) # Default to 0 (disabled)
731727
else:
732728
if setting == 'ingest_timeout_minutes':
733729
result[setting] = cwa_db.cwa_settings.get(setting, 15) # Default to 15 minutes
@@ -739,8 +735,6 @@ def set_cwa_settings():
739735
result[setting] = cwa_db.cwa_settings.get(setting, 2) # Default to 2 AM
740736
elif setting == 'duplicate_scan_debounce_seconds':
741737
result[setting] = cwa_db.cwa_settings.get(setting, 30)
742-
elif setting == 'duplicate_auto_resolve_cooldown_minutes':
743-
result[setting] = cwa_db.cwa_settings.get(setting, 0) # Default to 0 (disabled)
744738

745739
# Handle float settings
746740
for setting in float_settings:
@@ -2047,283 +2041,3 @@ def set_profile_picture():
20472041
return render_title_template("profile_pictures.html",
20482042
title=_("CWA Profile Picture Management (WIP)"),
20492043
page="profile-picture")
2050-
2051-
2052-
# ========================================
2053-
# Full Text Search (FTS) Management
2054-
# ========================================
2055-
2056-
def _get_fts_status_from_calibredb():
2057-
"""
2058-
Get FTS indexing status from calibredb.
2059-
Returns dict with: enabled, indexed, total, percentage, error
2060-
"""
2061-
from .admin import get_calibre_binarypath
2062-
2063-
result = {
2064-
'enabled': False,
2065-
'indexed': 0,
2066-
'total': 0,
2067-
'percentage': 0.0,
2068-
'error': None
2069-
}
2070-
2071-
if not config.config_calibre_dir:
2072-
result['error'] = _('No library path configured')
2073-
return result
2074-
2075-
calibredb_path = get_calibre_binarypath("calibredb")
2076-
if not calibredb_path or not os.path.isfile(calibredb_path):
2077-
result['error'] = _('calibredb not found')
2078-
return result
2079-
2080-
try:
2081-
# Set up environment with LD_LIBRARY_PATH for Calibre libraries
2082-
env = os.environ.copy()
2083-
env['LD_LIBRARY_PATH'] = '/app/calibre/lib'
2084-
2085-
# Run calibredb fts_index status
2086-
cmd = [calibredb_path, 'fts_index', 'status', '--library-path', config.config_calibre_dir]
2087-
proc_result = subprocess.run(
2088-
cmd,
2089-
stdout=subprocess.PIPE,
2090-
stderr=subprocess.PIPE,
2091-
text=True,
2092-
timeout=10,
2093-
env=env
2094-
)
2095-
2096-
# Exit code 0 = enabled, exit code 2 = disabled (both are valid responses)
2097-
if proc_result.returncode in [0, 2]:
2098-
output = proc_result.stdout.strip()
2099-
2100-
# Check if enabled or disabled
2101-
if 'disabled' in output.lower():
2102-
result['enabled'] = False
2103-
# When disabled, there are no books to count
2104-
result['indexed'] = 0
2105-
result['total'] = 0
2106-
result['percentage'] = 0.0
2107-
return result
2108-
elif 'enabled' in output.lower():
2109-
result['enabled'] = True
2110-
2111-
# Parse "X of Y books" pattern
2112-
match = re.search(r'(\d+)\s+of\s+(\d+)\s+books', output)
2113-
if match:
2114-
result['indexed'] = int(match.group(1))
2115-
result['total'] = int(match.group(2))
2116-
if result['total'] > 0:
2117-
result['percentage'] = (result['indexed'] / result['total']) * 100
2118-
else:
2119-
result['error'] = proc_result.stderr.strip() or _('Failed to get FTS status')
2120-
2121-
except subprocess.TimeoutExpired:
2122-
result['error'] = _('Timeout while checking FTS status')
2123-
except Exception as ex:
2124-
result['error'] = str(ex)
2125-
log.error(f"Error getting FTS status: {ex}")
2126-
2127-
return result
2128-
2129-
2130-
def _initialize_fts_index():
2131-
"""
2132-
Initialize or disable Full Text Search indexing based on config.
2133-
Returns a tuple of (success: bool, message: str or None)
2134-
"""
2135-
from .admin import get_calibre_binarypath
2136-
2137-
if not config.config_calibre_dir:
2138-
return False, _('No library path configured')
2139-
2140-
fts_db_path = os.path.join(config.config_calibre_dir, "full-text-search.db")
2141-
2142-
# If FTS disabled but database exists, disable indexing
2143-
if not config.config_fulltext_search and os.path.exists(fts_db_path):
2144-
try:
2145-
calibredb_path = get_calibre_binarypath("calibredb")
2146-
if not calibredb_path or not os.path.isfile(calibredb_path):
2147-
log.warning("calibredb not found, cannot disable FTS indexing")
2148-
return False, _('calibredb not available. Cannot stop FTS indexing.')
2149-
2150-
env = os.environ.copy()
2151-
env['LD_LIBRARY_PATH'] = '/app/calibre/lib'
2152-
2153-
cmd = [calibredb_path, 'fts_index', 'disable', '--library-path', config.config_calibre_dir]
2154-
log.info("Disabling FTS index: %s", ' '.join(cmd))
2155-
2156-
result = subprocess.run(
2157-
cmd,
2158-
input='disable\n', # Must type "disable" to confirm
2159-
stdout=subprocess.PIPE,
2160-
stderr=subprocess.PIPE,
2161-
text=True,
2162-
timeout=30,
2163-
env=env
2164-
)
2165-
2166-
if result.returncode == 0:
2167-
log.info("FTS indexing disabled successfully")
2168-
return True, _('Full Text Search indexing has been disabled and stopped.')
2169-
else:
2170-
log.error("Failed to disable FTS indexing: %s", result.stderr.strip())
2171-
return False, _('Failed to disable FTS indexing: %(error)s', error=result.stderr.strip())
2172-
except Exception as ex:
2173-
log.error("Failed to disable FTS indexing: %s", ex)
2174-
return False, _('Error disabling FTS indexing: %(error)s', error=str(ex))
2175-
2176-
# If FTS not enabled, nothing to do
2177-
if not config.config_fulltext_search:
2178-
return True, None
2179-
2180-
# Check if FTS database already exists AND is enabled
2181-
if os.path.exists(fts_db_path):
2182-
# Check current status to see if it's actually enabled
2183-
current_status = _get_fts_status_from_calibredb()
2184-
if current_status['enabled']:
2185-
log.debug("FTS database already exists and is enabled at %s", fts_db_path)
2186-
return True, None
2187-
# If disabled, fall through to enable it
2188-
2189-
# Try to enable FTS indexing using calibredb
2190-
try:
2191-
calibredb_path = get_calibre_binarypath("calibredb")
2192-
if not calibredb_path or not os.path.isfile(calibredb_path):
2193-
log.warning("calibredb not found, cannot initialize FTS indexing")
2194-
return False, _('Full Text Search enabled but calibredb not available. FTS indexing cannot be initialized.')
2195-
2196-
# Run calibredb fts_index enable
2197-
env = os.environ.copy()
2198-
env['LD_LIBRARY_PATH'] = '/app/calibre/lib'
2199-
2200-
cmd = [calibredb_path, 'fts_index', 'enable', '--library-path', config.config_calibre_dir]
2201-
log.info("Initializing FTS index: %s", ' '.join(cmd))
2202-
2203-
result = subprocess.run(
2204-
cmd,
2205-
stdout=subprocess.PIPE,
2206-
stderr=subprocess.PIPE,
2207-
text=True,
2208-
timeout=30,
2209-
env=env
2210-
)
2211-
2212-
if result.returncode == 0:
2213-
log.info("FTS indexing enabled successfully: %s", result.stdout.strip())
2214-
return True, _('Full Text Search indexing enabled. Books are being indexed in the background.')
2215-
else:
2216-
log.error("Failed to enable FTS indexing: %s", result.stderr.strip())
2217-
return False, _('Failed to enable FTS indexing: %(error)s', error=result.stderr.strip())
2218-
2219-
except Exception as ex:
2220-
log.error("Failed to initialize FTS indexing: %s", ex)
2221-
return False, _('Error initializing FTS indexing: %(error)s', error=str(ex))
2222-
2223-
2224-
@cwa_settings.route('/fts-status', methods=['GET'])
2225-
@login_required_if_no_ano
2226-
@admin_required
2227-
def get_fts_status():
2228-
"""
2229-
Get current FTS indexing status.
2230-
Returns JSON with status information.
2231-
"""
2232-
status = _get_fts_status_from_calibredb()
2233-
2234-
# Determine if search is available (90% threshold)
2235-
status['available'] = status['enabled'] and status['percentage'] >= 90.0
2236-
2237-
# Check if indexing is currently active by comparing two sequential checks
2238-
# If indexed count changes, indexing is active
2239-
if status['enabled'] and status['indexed'] < status['total']:
2240-
sleep(0.5) # Brief pause
2241-
status2 = _get_fts_status_from_calibredb()
2242-
status['active'] = status2['indexed'] > status['indexed']
2243-
else:
2244-
status['active'] = False
2245-
2246-
return jsonify(status)
2247-
2248-
2249-
@cwa_settings.route('/fts-action', methods=['POST'])
2250-
@csrf.exempt
2251-
@login_required_if_no_ano
2252-
@admin_required
2253-
def fts_action():
2254-
"""
2255-
Execute FTS actions: enable, disable, reindex.
2256-
Returns JSON with success status and message.
2257-
"""
2258-
from .admin import get_calibre_binarypath
2259-
2260-
action = request.form.get('action')
2261-
2262-
if action not in ['enable', 'disable', 'reindex']:
2263-
return jsonify({'success': False, 'message': _('Invalid action')}), 400
2264-
2265-
calibredb_path = get_calibre_binarypath("calibredb")
2266-
if not calibredb_path or not os.path.isfile(calibredb_path):
2267-
return jsonify({'success': False, 'message': _('calibredb not available')}), 500
2268-
2269-
if not config.config_calibre_dir:
2270-
return jsonify({'success': False, 'message': _('No library path configured')}), 500
2271-
2272-
try:
2273-
env = os.environ.copy()
2274-
env['LD_LIBRARY_PATH'] = '/app/calibre/lib'
2275-
2276-
if action == 'enable':
2277-
# Update config
2278-
config.config_fulltext_search = True
2279-
config.save()
2280-
2281-
# Initialize FTS
2282-
success, message = _initialize_fts_index()
2283-
if success:
2284-
return jsonify({'success': True, 'message': message or _('FTS indexing enabled successfully')})
2285-
else:
2286-
return jsonify({'success': False, 'message': message}), 500
2287-
2288-
elif action == 'disable':
2289-
# Update config
2290-
try:
2291-
config.config_fulltext_search = False
2292-
config.save()
2293-
log.info("FTS config setting disabled and saved")
2294-
except Exception as save_ex:
2295-
log.error(f"Error saving config during FTS disable: {save_ex}")
2296-
return jsonify({'success': False, 'message': f'Failed to save config: {str(save_ex)}'}), 500
2297-
2298-
# Disable FTS
2299-
success, message = _initialize_fts_index()
2300-
if success:
2301-
return jsonify({'success': True, 'message': message or _('FTS indexing disabled successfully')})
2302-
else:
2303-
return jsonify({'success': False, 'message': message}), 500
2304-
2305-
elif action == 'reindex':
2306-
if not config.config_fulltext_search:
2307-
return jsonify({'success': False, 'message': _('FTS must be enabled before reindexing')}), 400
2308-
2309-
cmd = [calibredb_path, 'fts_index', 'reindex', '--library-path', config.config_calibre_dir]
2310-
log.info("Reindexing FTS: %s", ' '.join(cmd))
2311-
2312-
result = subprocess.run(
2313-
cmd,
2314-
input='reindex\n', # Must type "reindex" to confirm
2315-
stdout=subprocess.PIPE,
2316-
stderr=subprocess.PIPE,
2317-
text=True,
2318-
timeout=30,
2319-
env=env
2320-
)
2321-
2322-
if result.returncode == 0:
2323-
return jsonify({'success': True, 'message': _('FTS reindexing started successfully')})
2324-
else:
2325-
return jsonify({'success': False, 'message': result.stderr.strip()}), 500
2326-
2327-
except Exception as ex:
2328-
log.error(f"FTS action failed: {ex}")
2329-
return jsonify({'success': False, 'message': str(ex)}), 500

0 commit comments

Comments
 (0)