bertrend 0.4.8__tar.gz → 0.4.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bertrend-0.4.8 → bertrend-0.4.9}/PKG-INFO +1 -1
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/queue_management/bertrend_worker.py +82 -21
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/queue_management/queue_manager.py +49 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/queue_management/rabbitmq_config.py +4 -1
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/queue_monitor/app.py +156 -5
- bertrend-0.4.9/bertrend/tests/services/article_scoring/test_article_scoring_server.py +84 -0
- bertrend-0.4.9/bertrend/tests/services/queue_management/test_bertrend_worker.py +294 -0
- bertrend-0.4.9/bertrend/tests/services/queue_management/test_queue_manager.py +146 -0
- bertrend-0.4.9/bertrend/tests/services/summary/__init__.py +4 -0
- bertrend-0.4.9/bertrend/tests/utils/__init__.py +4 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/pyproject.toml +1 -1
- {bertrend-0.4.8 → bertrend-0.4.9}/AUTHORS.txt +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/LICENSE.md +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/README.md +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/BERTopicModel.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/BERTrend.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/article_scoring/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/article_scoring/article_scoring.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/article_scoring/prompts.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/article_scoring/scoring_agent.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/common/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/common/apscheduler_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/common/crontab_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/common/date_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/common/mail_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/common/scheduler_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/config/feeds/arxiv_feed.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/config/feeds/decarbonation_feed.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/config/feeds/feed_deep_research_example.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/config/feeds/llm_en_feed.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/config/feeds/llm_feed.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/config/feeds/nlp_feed.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/config/feeds/rte_feed.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/config/newsletters/arxiv_newsletter_from_last.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/config/newsletters/decarbonation_newsletter_from_last.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/config/newsletters/llm_en_newsletter_from_last.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/config/newsletters/llm_newsletter_from_last.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/config/newsletters/nlp_newsletter_from_last.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/config/newsletters/rte_newsletter_from_last.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/data_provider/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/data_provider/__main__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/data_provider/arxiv_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/data_provider/atom_feed_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/data_provider/bing_news_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/data_provider/data_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/data_provider/data_provider_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/data_provider/deep_research_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/data_provider/google_news_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/data_provider/newscatcher_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/data_provider/rss_feed_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/data_provider/utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/curebot/.streamlit/config.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/curebot/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/curebot/app.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/curebot/app_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/curebot/config.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/curebot/import_extraction_article.ipynb +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/curebot/prompts.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/curebot/start_newsletter_generator.sh +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/curebot/tabs/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/curebot/tabs/tab1.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/curebot/tabs/tab2.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/curebot/tabs/tab3.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/geoviz/.streamlit/config.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/geoviz/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/geoviz/app.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/geoviz/backend.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/start_apps.sh +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/exploration/stop_apps.sh +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/install_feeds_and_newsletters.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/newsletters/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/newsletters/__main__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/newsletters/newsletter_generation.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/newsletters/utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/.streamlit/config.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/.streamlit/secrets.toml.example +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/app.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/authentication.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/automated_report_generation.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/dashboard_analysis.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/dashboard_common.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/dashboard_comparative.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/dashboard_signals.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/data_model.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/detailed_report_template.html +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/feeds_common.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/feeds_config.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/feeds_data.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/i18n.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/i18n_translations.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/llm_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/models_info.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/perf_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/process_new_data.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/report_generation.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/report_generation_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/start_demo.sh +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/prospective_demo/utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/bertrend_service.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/config/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/config/default_config.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/config/settings.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/models/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/models/bertrend_app_models.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/models/data_provider_models.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/models/newsletters_models.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/routers/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/routers/bertrend_app.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/routers/data_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/routers/info.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/routers/newsletters.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/start.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/status.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/bertrend/stop.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/queue_management/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/queue_management/client.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/queue_management/docker-compose-rabbitmq.yml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/queue_management/start_rabbitmq.sh +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/queue_monitor/.streamlit/config.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/queue_monitor/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/utils/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/utils/logging_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/config/bertopic_default_config.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/config/bertrend_default_config.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/config/parameters.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/config/services_default_config.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/demos_utils/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/demos_utils/data_loading_component.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/demos_utils/embed_documents_component.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/demos_utils/i18n.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/demos_utils/i18n_translations.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/demos_utils/icons.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/demos_utils/parameters_component.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/demos_utils/state_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/start_summarizer_app.sh +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/start_topic_analysis_app.sh +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/start_weak_signals_app.sh +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/streamlit_components/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/streamlit_components/clickable_df_component.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/streamlit_components/input_with_pills_component.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/summarization/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/summarization/summarizer_app.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/topic_analysis/.streamlit/config.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/topic_analysis/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/topic_analysis/app.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/topic_analysis/app_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/topic_analysis/demo_pages/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/topic_analysis/demo_pages/explore_topics.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/topic_analysis/demo_pages/newsletters_generation.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/topic_analysis/demo_pages/temporal_visualizations.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/topic_analysis/demo_pages/topic_visualizations.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/topic_analysis/demo_pages/training_page.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/topic_analysis/i18n_translations.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/weak_signals/.streamlit/config.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/weak_signals/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/weak_signals/app.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/weak_signals/i18n_translations.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/demos/weak_signals/visualizations_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/llm_utils/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/llm_utils/agent_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/llm_utils/newsletter.css +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/llm_utils/newsletter_features.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/llm_utils/newsletter_model.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/llm_utils/newsletter_outlook_template.html +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/llm_utils/newsletter_template.html +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/llm_utils/openai_client.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/llm_utils/prompts.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/metrics/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/metrics/temporal_metrics_embedding.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/metrics/topic_metrics.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/resources/common_ngrams.json +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/resources/stopwords-en.json +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/resources/stopwords-fr.json +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/resources/stopwords-rte.json +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/article_scoring_server/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/article_scoring_server/config/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/article_scoring_server/config/default_config.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/article_scoring_server/config/settings.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/article_scoring_server/models.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/article_scoring_server/routers/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/article_scoring_server/routers/info.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/article_scoring_server/routers/scoring.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/article_scoring_server/scoring_service.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/article_scoring_server/start.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/authentication.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/cert.pem +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_client.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/README.md +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/bertrend_client_registry.json +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/config/default_config.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/config/settings.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/main.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/models.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/requirements.txt +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/routers/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/routers/authentication.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/routers/embeddings.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/routers/info.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/security.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/start.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/status.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_server/stop.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/embedding_service.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/key.pem +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/.dockerignore +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/Docker_setup.md +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/Dockerfile +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/dashboard_scheduling.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/docker-compose.yml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/job_utils/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/job_utils/job_functions.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/models/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/models/scheduling_models.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/requirements.txt +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/routers/info.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/routers/scheduling.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/scheduling_service.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/scheduling/start_docker_scheduling_service.sh +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summarizer.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary/abstractive_summarizer.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary/chatgpt_summarizer.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary/extractive_summarizer.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary/lexrank.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary/prompts.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary_client.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary_server/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary_server/config/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary_server/config/default_config.toml +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary_server/config/settings.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary_server/main.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary_server/models.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary_server/routers/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary_server/routers/info.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary_server/routers/summarize.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/services/summary_server/start.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/README_integration_tests.md +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/apps/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/apps/test_process_new_data.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/conftest.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/core/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/core/test_bertrend.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/core/test_data_structure.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/core/test_representative_docs.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/core/test_temporal_metrics_embedding.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/core/test_topic_description.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/core/test_topic_metrics.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/core/test_topic_model.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/core/test_trend_analysis_data_structure.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/core/test_trend_analysis_prompts.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/core/test_trend_analysis_visualizations.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/core/test_trend_analysis_weak_signals.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/core/test_visualizations.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/data_provider/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/data_provider/test_arxiv_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/data_provider/test_bing_news_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/data_provider/test_data_provider_base.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/data_provider/test_data_provider_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/data_provider/test_deep_research_live.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/data_provider/test_deep_research_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/data_provider/test_google_news_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/data_provider/test_newscatcher_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/data_provider/test_rss_atom_provider.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/demos/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/demos/summarization/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/demos/summarization/test_summarizer_app.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/llm/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/llm/test_agent_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/llm/test_article_scoring.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/llm/test_article_scoring_models.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/llm/test_newsletter_features.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/llm/test_newsletter_model.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/llm/test_openai_client.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/__init__.py +0 -0
- {bertrend-0.4.8/bertrend/tests/services/embedding → bertrend-0.4.9/bertrend/tests/services/article_scoring}/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/bertrend/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/bertrend/test_bertrend_service.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/bertrend/test_models.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/bertrend/test_routers_bertrend_app.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/bertrend/test_routers_info.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/bertrend/test_routers_newsletters.py +0 -0
- {bertrend-0.4.8/bertrend/tests/services/embedding_server → bertrend-0.4.9/bertrend/tests/services/embedding}/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/embedding/test_embedding_client.py +0 -0
- {bertrend-0.4.8/bertrend/tests/services/queue → bertrend-0.4.9/bertrend/tests/services/embedding_server}/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/embedding_server/test_models.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/embedding_server/test_routers.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/embedding_server/test_security.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/embedding_server/test_settings.py +0 -0
- {bertrend-0.4.8/bertrend/tests/services/scheduling → bertrend-0.4.9/bertrend/tests/services/queue}/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/queue/test_bertrend_worker.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/queue/test_client.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/queue/test_queue_manager.py +0 -0
- {bertrend-0.4.8/bertrend/tests/services/summarizer → bertrend-0.4.9/bertrend/tests/services/queue_management}/__init__.py +0 -0
- {bertrend-0.4.8/bertrend/tests/services/summary → bertrend-0.4.9/bertrend/tests/services/scheduling}/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/scheduling/test_job_exception_fix.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/scheduling/test_scheduling_service.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/scheduling/test_stress_test.py +0 -0
- {bertrend-0.4.8/bertrend/tests/utils → bertrend-0.4.9/bertrend/tests/services/summarizer}/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/summarizer/test_abstractive_summarizer.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/summarizer/test_chatgpt_summarizer.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/summarizer/test_extractive_summarizer.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/summarizer/test_summarizer.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/summary/test_summary_client.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/summary/test_summary_config.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/services/summary/test_summary_server.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/test_installation.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/test_integration.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/utils/test_apscheduler_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/utils/test_cache_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/utils/test_config_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/utils/test_crontab_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/utils/test_data_loading.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/utils/test_date_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/utils/test_lazy_scheduler.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/utils/test_mail_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/utils/test_multiworker.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/utils/test_scheduler_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/tests/utils/test_utils_init.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/topic_analysis/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/topic_analysis/data_structure.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/topic_analysis/prompts.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/topic_analysis/representative_docs.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/topic_analysis/topic_description.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/topic_analysis/visualizations.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/trend_analysis/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/trend_analysis/data_structure.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/trend_analysis/prompts.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/trend_analysis/signal_llm_template_en.html +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/trend_analysis/signal_llm_template_fr.html +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/trend_analysis/visualizations.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/trend_analysis/weak_signals.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/utils/__init__.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/utils/cache_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/utils/config_utils.py +0 -0
- {bertrend-0.4.8 → bertrend-0.4.9}/bertrend/utils/data_loading.py +0 -0
|
@@ -253,6 +253,45 @@ class BertrendWorker:
|
|
|
253
253
|
"traceback": traceback.format_exc(),
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
+
def _get_retry_count(self, message: aio_pika.abc.AbstractIncomingMessage) -> int:
|
|
257
|
+
"""Return the current retry count stored in the message header x-retry-count."""
|
|
258
|
+
headers = message.headers or {}
|
|
259
|
+
try:
|
|
260
|
+
return int(headers.get("x-retry-count", 0))
|
|
261
|
+
except (TypeError, ValueError):
|
|
262
|
+
return 0
|
|
263
|
+
|
|
264
|
+
async def _nack_or_discard(
|
|
265
|
+
self,
|
|
266
|
+
message: aio_pika.abc.AbstractIncomingMessage,
|
|
267
|
+
reason: str,
|
|
268
|
+
correlation_id: str | None,
|
|
269
|
+
):
|
|
270
|
+
"""
|
|
271
|
+
Retry the message if the retry limit has not been reached, otherwise
|
|
272
|
+
reject it (requeue=False) so it goes to the DLQ.
|
|
273
|
+
|
|
274
|
+
Delegates the retry-limit check to republish_with_retry(), which
|
|
275
|
+
returns False when the limit is reached (and skips publishing).
|
|
276
|
+
The original message is always rejected with requeue=False so that
|
|
277
|
+
RabbitMQ does not re-deliver the same copy.
|
|
278
|
+
"""
|
|
279
|
+
retry_count = self._get_retry_count(message)
|
|
280
|
+
republished = await self.queue_manager.republish_with_retry(
|
|
281
|
+
message, retry_count
|
|
282
|
+
)
|
|
283
|
+
if republished:
|
|
284
|
+
logger.warning(
|
|
285
|
+
f"Message {correlation_id} failed (attempt {retry_count + 1}/{self.config.max_retries}) "
|
|
286
|
+
f"— republished with incremented retry count. Reason: {reason}"
|
|
287
|
+
)
|
|
288
|
+
else:
|
|
289
|
+
logger.warning(
|
|
290
|
+
f"Message {correlation_id} exceeded max retries ({self.config.max_retries}) "
|
|
291
|
+
f"— sending to DLQ. Reason: {reason}"
|
|
292
|
+
)
|
|
293
|
+
await message.reject(requeue=False)
|
|
294
|
+
|
|
256
295
|
async def callback(
|
|
257
296
|
self,
|
|
258
297
|
message: aio_pika.abc.AbstractIncomingMessage,
|
|
@@ -268,41 +307,63 @@ class BertrendWorker:
|
|
|
268
307
|
|
|
269
308
|
logger.info(f"Request endpoint: {request_data.get('endpoint')}")
|
|
270
309
|
|
|
271
|
-
# Process request
|
|
272
|
-
response_data = await
|
|
310
|
+
# Process request with a timeout to avoid blocking the queue indefinitely
|
|
311
|
+
response_data = await asyncio.wait_for(
|
|
312
|
+
self.process_request(request_data),
|
|
313
|
+
timeout=self.config.job_timeout,
|
|
314
|
+
)
|
|
273
315
|
|
|
274
316
|
# Add metadata
|
|
275
317
|
response_data["correlation_id"] = correlation_id
|
|
276
318
|
response_data["request_data"] = request_data
|
|
277
319
|
|
|
278
|
-
# Publish response/error if reply_to is specified
|
|
279
|
-
if message.reply_to:
|
|
280
|
-
if response_data.get("status") == "error":
|
|
281
|
-
await self.queue_manager.publish_error(
|
|
282
|
-
error_data=response_data, correlation_id=correlation_id
|
|
283
|
-
)
|
|
284
|
-
else:
|
|
285
|
-
await self.queue_manager.publish_response(
|
|
286
|
-
response_data=response_data, correlation_id=correlation_id
|
|
287
|
-
)
|
|
288
|
-
|
|
289
|
-
# Acknowledge message
|
|
290
|
-
await message.ack()
|
|
291
|
-
logger.info(
|
|
292
|
-
f"Completed request: {correlation_id} - Status: {response_data.get('status')}"
|
|
293
|
-
)
|
|
294
|
-
|
|
295
320
|
except json.JSONDecodeError as e:
|
|
296
321
|
logger.error(f"Invalid message format: {str(e)}")
|
|
297
322
|
# Reject and don't requeue invalid messages
|
|
298
323
|
await message.reject(requeue=False)
|
|
324
|
+
return
|
|
325
|
+
|
|
326
|
+
except asyncio.TimeoutError:
|
|
327
|
+
await self._nack_or_discard(
|
|
328
|
+
message,
|
|
329
|
+
reason=f"job timed out after {self.config.job_timeout}s",
|
|
330
|
+
correlation_id=correlation_id,
|
|
331
|
+
)
|
|
332
|
+
return
|
|
299
333
|
|
|
300
334
|
except Exception as e:
|
|
301
335
|
logger.error(f"Error processing message: {str(e)}")
|
|
302
336
|
logger.error(traceback.format_exc())
|
|
337
|
+
await self._nack_or_discard(
|
|
338
|
+
message,
|
|
339
|
+
reason=str(e),
|
|
340
|
+
correlation_id=correlation_id,
|
|
341
|
+
)
|
|
342
|
+
return
|
|
303
343
|
|
|
304
|
-
|
|
305
|
-
|
|
344
|
+
# Acknowledge message before publishing the response, so that the message
|
|
345
|
+
# is always acked regardless of any subsequent publish failure
|
|
346
|
+
await message.ack()
|
|
347
|
+
logger.info(
|
|
348
|
+
f"Completed request: {correlation_id} - Status: {response_data.get('status')}"
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
# Publish response/error if reply_to is specified
|
|
352
|
+
if message.reply_to:
|
|
353
|
+
try:
|
|
354
|
+
if response_data.get("status") == "error":
|
|
355
|
+
await self.queue_manager.publish_error(
|
|
356
|
+
error_data=response_data, correlation_id=correlation_id
|
|
357
|
+
)
|
|
358
|
+
else:
|
|
359
|
+
await self.queue_manager.publish_response(
|
|
360
|
+
response_data=response_data, correlation_id=correlation_id
|
|
361
|
+
)
|
|
362
|
+
except Exception as e:
|
|
363
|
+
logger.error(
|
|
364
|
+
f"Failed to publish response for {correlation_id}: {str(e)}"
|
|
365
|
+
)
|
|
366
|
+
logger.error(traceback.format_exc())
|
|
306
367
|
|
|
307
368
|
async def start(self):
|
|
308
369
|
"""Start the worker"""
|
{bertrend-0.4.8 → bertrend-0.4.9}/bertrend/bertrend_apps/services/queue_management/queue_manager.py
RENAMED
|
@@ -159,6 +159,55 @@ class QueueManager:
|
|
|
159
159
|
|
|
160
160
|
await queue.consume(callback, no_ack=False)
|
|
161
161
|
|
|
162
|
+
async def republish_with_retry(
|
|
163
|
+
self,
|
|
164
|
+
original_message: aio_pika.abc.AbstractIncomingMessage,
|
|
165
|
+
retry_count: int,
|
|
166
|
+
) -> bool:
|
|
167
|
+
"""Republish a failed message with an incremented x-retry-count header.
|
|
168
|
+
|
|
169
|
+
RabbitMQ does not modify headers on requeue, so we must republish
|
|
170
|
+
manually with the updated counter instead of using nack(requeue=True).
|
|
171
|
+
|
|
172
|
+
Returns True if the message was republished, False if the retry limit
|
|
173
|
+
has already been reached and the message was not republished.
|
|
174
|
+
"""
|
|
175
|
+
new_retry_count = retry_count + 1
|
|
176
|
+
if new_retry_count > self.config.max_retries:
|
|
177
|
+
logger.warning(
|
|
178
|
+
f"Message {original_message.correlation_id} has reached the maximum "
|
|
179
|
+
f"retry limit ({self.config.max_retries}) — not republishing."
|
|
180
|
+
)
|
|
181
|
+
return False
|
|
182
|
+
|
|
183
|
+
if not self.channel or self.channel.is_closed:
|
|
184
|
+
await self.connect()
|
|
185
|
+
|
|
186
|
+
# Carry over all existing headers and bump the retry counter
|
|
187
|
+
headers = dict(original_message.headers or {})
|
|
188
|
+
headers["x-retry-count"] = new_retry_count
|
|
189
|
+
|
|
190
|
+
message = aio_pika.Message(
|
|
191
|
+
body=original_message.body,
|
|
192
|
+
headers=headers,
|
|
193
|
+
delivery_mode=aio_pika.DeliveryMode.PERSISTENT,
|
|
194
|
+
priority=original_message.priority,
|
|
195
|
+
correlation_id=original_message.correlation_id,
|
|
196
|
+
content_type=original_message.content_type,
|
|
197
|
+
reply_to=original_message.reply_to,
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
await self.channel.default_exchange.publish(
|
|
201
|
+
message,
|
|
202
|
+
routing_key=self.config.request_queue,
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
logger.info(
|
|
206
|
+
f"Republished message {original_message.correlation_id} "
|
|
207
|
+
f"with x-retry-count={new_retry_count}"
|
|
208
|
+
)
|
|
209
|
+
return True
|
|
210
|
+
|
|
162
211
|
async def publish_response(self, response_data: dict, correlation_id: str):
|
|
163
212
|
"""Publish response to response queue_management"""
|
|
164
213
|
if not self.channel or self.channel.is_closed:
|
|
@@ -36,5 +36,8 @@ class RabbitMQConfig:
|
|
|
36
36
|
prefetch_count: int = int(os.getenv("RABBITMQ_PREFETCH_COUNT", 1))
|
|
37
37
|
|
|
38
38
|
# Retry configuration
|
|
39
|
-
max_retries: int = int(os.getenv("RABBITMQ_MAX_RETRIES",
|
|
39
|
+
max_retries: int = int(os.getenv("RABBITMQ_MAX_RETRIES", 2))
|
|
40
40
|
retry_delay: int = int(os.getenv("RABBITMQ_RETRY_DELAY", 5000)) # milliseconds
|
|
41
|
+
|
|
42
|
+
# Job timeout: max seconds a single job may run before being nacked (default: 1 hour)
|
|
43
|
+
job_timeout: int = int(os.getenv("RABBITMQ_JOB_TIMEOUT", 3600))
|
|
@@ -60,6 +60,18 @@ class RabbitMQAdminClient:
|
|
|
60
60
|
r.raise_for_status()
|
|
61
61
|
return r.json()
|
|
62
62
|
|
|
63
|
+
def get_consumers(self) -> List[Dict[str, Any]]:
|
|
64
|
+
url = f"{self.base_url}/api/consumers/{self._vhost_path()}"
|
|
65
|
+
r = self._session.get(url, timeout=5)
|
|
66
|
+
r.raise_for_status()
|
|
67
|
+
return r.json()
|
|
68
|
+
|
|
69
|
+
def get_channels(self) -> List[Dict[str, Any]]:
|
|
70
|
+
url = f"{self.base_url}/api/channels"
|
|
71
|
+
r = self._session.get(url, timeout=5)
|
|
72
|
+
r.raise_for_status()
|
|
73
|
+
return r.json()
|
|
74
|
+
|
|
63
75
|
def peek_messages(self, name: str, count: int = 10) -> List[Dict[str, Any]]:
|
|
64
76
|
url = f"{self.base_url}/api/queues/{self._vhost_path()}/{quote(name, safe='')}/get"
|
|
65
77
|
payload = {
|
|
@@ -262,7 +274,14 @@ client = RabbitMQAdminClient(client_cfg, management_url=mgmt_url)
|
|
|
262
274
|
|
|
263
275
|
# --- Data Fetching ---
|
|
264
276
|
queue_data = {}
|
|
265
|
-
global_stats = {
|
|
277
|
+
global_stats = {
|
|
278
|
+
"total": 0,
|
|
279
|
+
"requests": 0,
|
|
280
|
+
"responses": 0,
|
|
281
|
+
"failed": 0,
|
|
282
|
+
"unacked": 0,
|
|
283
|
+
"consumers": 0,
|
|
284
|
+
}
|
|
266
285
|
error_msg = None
|
|
267
286
|
|
|
268
287
|
try:
|
|
@@ -272,9 +291,14 @@ try:
|
|
|
272
291
|
|
|
273
292
|
# Aggregation
|
|
274
293
|
global_stats["total"] += info.get("messages", 0)
|
|
275
|
-
global_stats["ready"] += info.get("messages_ready", 0)
|
|
276
294
|
global_stats["unacked"] += info.get("messages_unacknowledged", 0)
|
|
277
295
|
global_stats["consumers"] += info.get("consumers", 0)
|
|
296
|
+
if "requests" in q:
|
|
297
|
+
global_stats["requests"] += info.get("messages", 0)
|
|
298
|
+
elif "responses" in q or "response" in q:
|
|
299
|
+
global_stats["responses"] += info.get("messages", 0)
|
|
300
|
+
elif "failed" in q:
|
|
301
|
+
global_stats["failed"] += info.get("messages", 0)
|
|
278
302
|
|
|
279
303
|
except Exception as e:
|
|
280
304
|
error_msg = str(e)
|
|
@@ -288,18 +312,33 @@ if error_msg:
|
|
|
288
312
|
|
|
289
313
|
# 1. Global Overview Row
|
|
290
314
|
st.markdown(f"### {DASHBOARD_ICON} System Overview")
|
|
291
|
-
kpi1, kpi2, kpi3, kpi4 = st.columns(
|
|
315
|
+
kpi1, kpi2, kpi3, kpi4, kpi5, kpi6 = st.columns(6)
|
|
292
316
|
kpi1.metric(
|
|
293
317
|
"Total Backlog", global_stats["total"], help="Total messages in all selected queues"
|
|
294
318
|
)
|
|
295
|
-
kpi2.metric(
|
|
319
|
+
kpi2.metric(
|
|
320
|
+
"Requests",
|
|
321
|
+
global_stats["requests"],
|
|
322
|
+
help="Messages in bertrend_requests queue",
|
|
323
|
+
)
|
|
296
324
|
kpi3.metric(
|
|
325
|
+
"Responses",
|
|
326
|
+
global_stats["responses"],
|
|
327
|
+
help="Messages in bertrend_responses queue",
|
|
328
|
+
)
|
|
329
|
+
kpi4.metric(
|
|
330
|
+
"Failed",
|
|
331
|
+
global_stats["failed"],
|
|
332
|
+
delta_color="inverse",
|
|
333
|
+
help="Messages in bertrend_failed queue",
|
|
334
|
+
)
|
|
335
|
+
kpi5.metric(
|
|
297
336
|
"Unacknowledged",
|
|
298
337
|
global_stats["unacked"],
|
|
299
338
|
delta_color="inverse",
|
|
300
339
|
help="Messages currently being processed but not acked",
|
|
301
340
|
)
|
|
302
|
-
|
|
341
|
+
kpi6.metric("Active Consumers", global_stats["consumers"])
|
|
303
342
|
|
|
304
343
|
st.divider()
|
|
305
344
|
|
|
@@ -327,6 +366,108 @@ else:
|
|
|
327
366
|
|
|
328
367
|
st.divider()
|
|
329
368
|
|
|
369
|
+
# B. Unacknowledged Messages Details
|
|
370
|
+
unacked_count = info.get("messages_unacknowledged", 0)
|
|
371
|
+
with st.expander(
|
|
372
|
+
f"Unacknowledged Messages ({unacked_count})",
|
|
373
|
+
expanded=unacked_count > 0,
|
|
374
|
+
):
|
|
375
|
+
if unacked_count == 0:
|
|
376
|
+
st.info("No unacknowledged messages in this queue.", icon=INFO_ICON)
|
|
377
|
+
else:
|
|
378
|
+
try:
|
|
379
|
+
all_consumers = client.get_consumers()
|
|
380
|
+
all_channels = client.get_channels()
|
|
381
|
+
|
|
382
|
+
# Filter consumers for this queue
|
|
383
|
+
queue_consumers = [
|
|
384
|
+
c
|
|
385
|
+
for c in all_consumers
|
|
386
|
+
if c.get("queue", {}).get("name") == qname
|
|
387
|
+
]
|
|
388
|
+
|
|
389
|
+
# Build a map of channel_name -> channel details
|
|
390
|
+
channel_map = {ch.get("name"): ch for ch in all_channels}
|
|
391
|
+
|
|
392
|
+
if not queue_consumers:
|
|
393
|
+
st.warning(
|
|
394
|
+
"Unacknowledged messages exist but no active consumers found. "
|
|
395
|
+
"Messages may be held by a disconnected consumer."
|
|
396
|
+
)
|
|
397
|
+
else:
|
|
398
|
+
st.caption(
|
|
399
|
+
f"{len(queue_consumers)} consumer(s) holding unacknowledged messages:"
|
|
400
|
+
)
|
|
401
|
+
for cons in queue_consumers:
|
|
402
|
+
ch_name = cons.get("channel_details", {}).get(
|
|
403
|
+
"name", ""
|
|
404
|
+
)
|
|
405
|
+
ch = channel_map.get(ch_name, {})
|
|
406
|
+
ch_unacked = ch.get("messages_unacknowledged", 0)
|
|
407
|
+
consumer_tag = cons.get("consumer_tag", "unknown")
|
|
408
|
+
peer_host = cons.get("channel_details", {}).get(
|
|
409
|
+
"peer_host", "?"
|
|
410
|
+
)
|
|
411
|
+
peer_port = cons.get("channel_details", {}).get(
|
|
412
|
+
"peer_port", ""
|
|
413
|
+
)
|
|
414
|
+
prefetch = cons.get("prefetch_count", 0)
|
|
415
|
+
ack_required = cons.get("ack_required", True)
|
|
416
|
+
|
|
417
|
+
with st.container(border=True):
|
|
418
|
+
cc1, cc2, cc3, cc4 = st.columns(4)
|
|
419
|
+
cc1.metric("Unacked (channel)", ch_unacked)
|
|
420
|
+
cc2.markdown(f"**Consumer Tag**\n`{consumer_tag}`")
|
|
421
|
+
cc3.markdown(
|
|
422
|
+
f"**Client**\n`{peer_host}:{peer_port}`"
|
|
423
|
+
)
|
|
424
|
+
cc4.markdown(
|
|
425
|
+
f"**Prefetch / Ack required**\n`{prefetch}` / `{ack_required}`"
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
# Channel-level stats
|
|
429
|
+
ch_stats = ch.get("message_stats", {})
|
|
430
|
+
ack_rate = (
|
|
431
|
+
ch_stats.get("ack_details", {}).get("rate", 0.0)
|
|
432
|
+
if ch_stats
|
|
433
|
+
else 0.0
|
|
434
|
+
)
|
|
435
|
+
deliver_rate = (
|
|
436
|
+
ch_stats.get("deliver_details", {}).get(
|
|
437
|
+
"rate", 0.0
|
|
438
|
+
)
|
|
439
|
+
if ch_stats
|
|
440
|
+
else 0.0
|
|
441
|
+
)
|
|
442
|
+
total_acked = (
|
|
443
|
+
ch_stats.get("ack", 0) if ch_stats else 0
|
|
444
|
+
)
|
|
445
|
+
total_delivered = (
|
|
446
|
+
ch_stats.get("deliver", 0) if ch_stats else 0
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
sc1, sc2, sc3, sc4 = st.columns(4)
|
|
450
|
+
sc1.metric("Ack Rate", f"{ack_rate:.2f}/s")
|
|
451
|
+
sc2.metric("Deliver Rate", f"{deliver_rate:.2f}/s")
|
|
452
|
+
sc3.metric("Total Acked", total_acked)
|
|
453
|
+
sc4.metric("Total Delivered", total_delivered)
|
|
454
|
+
|
|
455
|
+
# Connection info
|
|
456
|
+
conn = ch.get("connection_details", {})
|
|
457
|
+
if conn:
|
|
458
|
+
st.caption(
|
|
459
|
+
f"Connection: `{conn.get('name', ch_name)}` "
|
|
460
|
+
f"— state: `{ch.get('state', '?')}`"
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
except Exception as e:
|
|
464
|
+
st.error(
|
|
465
|
+
f"Failed to fetch consumer/channel details: {e}",
|
|
466
|
+
icon=ERROR_ICON,
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
st.divider()
|
|
470
|
+
|
|
330
471
|
# B. Message Peeking Interface
|
|
331
472
|
c_head, c_peek_n, c_sort = st.columns([3, 1, 1])
|
|
332
473
|
c_head.subheader("Message Browser")
|
|
@@ -546,6 +687,7 @@ else:
|
|
|
546
687
|
obj = d["obj"]
|
|
547
688
|
|
|
548
689
|
props = m.get("properties", {})
|
|
690
|
+
headers = props.get("headers") or {}
|
|
549
691
|
corr_id = props.get("correlation_id", "No-ID")
|
|
550
692
|
msg_size = (
|
|
551
693
|
m.get("payload_bytes", 0)
|
|
@@ -562,6 +704,9 @@ else:
|
|
|
562
704
|
info_tags.append(f"User: {d['user']}")
|
|
563
705
|
if d["model_id"]:
|
|
564
706
|
info_tags.append(f"Model: {d['model_id']}")
|
|
707
|
+
retry_count = headers.get("x-retry-count")
|
|
708
|
+
if retry_count is not None:
|
|
709
|
+
info_tags.append(f"Retry: {retry_count}")
|
|
565
710
|
|
|
566
711
|
info_str = f" | {' | '.join(info_tags)}" if info_tags else ""
|
|
567
712
|
label = f"#{idx + 1} | {fmt} | CID: {corr_id}{info_str} | {msg_size} bytes"
|
|
@@ -617,6 +762,12 @@ else:
|
|
|
617
762
|
"Key": "App ID",
|
|
618
763
|
"Val": str(props.get("app_id") or ""),
|
|
619
764
|
},
|
|
765
|
+
{
|
|
766
|
+
"Key": "x-retry-count",
|
|
767
|
+
"Val": str(headers.get("x-retry-count"))
|
|
768
|
+
if headers.get("x-retry-count") is not None
|
|
769
|
+
else "",
|
|
770
|
+
},
|
|
620
771
|
]
|
|
621
772
|
).dropna()
|
|
622
773
|
st.dataframe(meta_df, hide_index=True, width="stretch")
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Copyright (c) 2024-2026, RTE (https://www.rte-france.com)
|
|
2
|
+
# See AUTHORS.txt
|
|
3
|
+
# SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
# This file is part of BERTrend.
|
|
5
|
+
|
|
6
|
+
from unittest.mock import patch
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
from fastapi.testclient import TestClient
|
|
10
|
+
|
|
11
|
+
from bertrend.article_scoring.article_scoring import ArticleScore, CriteriaScores
|
|
12
|
+
from bertrend.llm_utils.agent_utils import ProcessingResult
|
|
13
|
+
from bertrend.services.article_scoring_server.scoring_service import app
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.fixture
|
|
17
|
+
def client():
|
|
18
|
+
return TestClient(app)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _make_article_score(
|
|
22
|
+
depth: int = 4, originality: int = 3, relevance_to_rte: int = 5
|
|
23
|
+
):
|
|
24
|
+
return ArticleScore(
|
|
25
|
+
scores=CriteriaScores(
|
|
26
|
+
depth_of_reporting=depth / 5,
|
|
27
|
+
originality_and_exclusivity=originality / 5,
|
|
28
|
+
source_quality_and_transparency=0.8,
|
|
29
|
+
accuracy_and_fact_checking_rigor=0.8,
|
|
30
|
+
clarity_and_accessibility=0.8,
|
|
31
|
+
balance_and_fairness=0.8,
|
|
32
|
+
narrative_and_engagement=0.8,
|
|
33
|
+
timeliness_and_relevance=0.8,
|
|
34
|
+
ethical_considerations_and_sensitivity=0.8,
|
|
35
|
+
rte_relevance_and_strategic_impact=relevance_to_rte / 5,
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_health(client):
|
|
41
|
+
response = client.get("/health")
|
|
42
|
+
assert response.status_code == 200
|
|
43
|
+
assert response.json() == {"status": "ok"}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_score_articles_success(client):
|
|
47
|
+
mock_results = [
|
|
48
|
+
ProcessingResult(input_index=0, output=_make_article_score()),
|
|
49
|
+
ProcessingResult(
|
|
50
|
+
input_index=1, output=_make_article_score(depth=2), error="timeout"
|
|
51
|
+
),
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
with patch(
|
|
55
|
+
"bertrend.services.article_scoring_server.routers.scoring.score_articles",
|
|
56
|
+
return_value=mock_results,
|
|
57
|
+
) as mock_score:
|
|
58
|
+
response = client.post("/score", json={"articles": ["article 1", "article 2"]})
|
|
59
|
+
|
|
60
|
+
assert response.status_code == 200
|
|
61
|
+
mock_score.assert_called_once_with(["article 1", "article 2"])
|
|
62
|
+
|
|
63
|
+
data = response.json()
|
|
64
|
+
assert len(data["results"]) == 2
|
|
65
|
+
assert data["results"][0]["article_index"] == 0
|
|
66
|
+
assert data["results"][0]["quality_metrics"] is not None
|
|
67
|
+
assert data["results"][0]["overall_quality"] == "POOR"
|
|
68
|
+
assert data["results"][0]["error"] is None
|
|
69
|
+
|
|
70
|
+
assert data["results"][1]["article_index"] == 1
|
|
71
|
+
assert data["results"][1]["quality_metrics"] is not None
|
|
72
|
+
assert data["results"][1]["overall_quality"] is None
|
|
73
|
+
assert data["results"][1]["error"] == "timeout"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_score_articles_backend_exception(client):
|
|
77
|
+
with patch(
|
|
78
|
+
"bertrend.services.article_scoring_server.routers.scoring.score_articles",
|
|
79
|
+
side_effect=RuntimeError("provider down"),
|
|
80
|
+
):
|
|
81
|
+
response = client.post("/score", json={"articles": ["article 1"]})
|
|
82
|
+
|
|
83
|
+
assert response.status_code == 500
|
|
84
|
+
assert "provider down" in response.json()["detail"]
|