Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions api/messages/messages_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ def add_nonprofit_to_hackathon(json):
# Update the hackathon document
hackathon_doc.set(hackathon_dict, merge=True)

# Clear cache to ensure fresh data is served
clear_cache()

return {
"message": "Nonprofit added to hackathon"
Expand Down Expand Up @@ -280,6 +282,9 @@ def remove_nonprofit_from_hackathon(json):
hackathon_data["nonprofits"] = updated_nonprofits
hackathon_doc.set(hackathon_data, merge=True)

# Clear cache to ensure fresh data is served
clear_cache()

logger.info(f"Remove Nonprofit from Hackathon End (nonprofit removed)")
return {
"message": "Nonprofit removed from hackathon"
Expand Down Expand Up @@ -1233,6 +1238,7 @@ def clear_cache():
doc_to_json.cache_clear()
get_single_hackathon_event.cache_clear()
get_single_hackathon_id.cache_clear()
get_hackathon_list.cache_clear()


@limits(calls=100, period=ONE_MINUTE)
Expand Down Expand Up @@ -1707,11 +1713,8 @@ def update_hackathon(transaction):
transaction = db.transaction()
update_hackathon(transaction)

# Clear cache for get_single_hackathon_event
get_single_hackathon_event.cache_clear()

# Clear cache for get_hackathon_list
doc_to_json.cache_clear()
# Clear all hackathon-related caches
clear_cache()


logger.info(f"Hackathon {'updated' if is_update else 'created'} successfully. ID: {doc_id}")
Expand Down
1 change: 1 addition & 0 deletions api/messages/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Tests for messages service
143 changes: 143 additions & 0 deletions api/messages/tests/test_cache_invalidation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
"""
Test cases for cache invalidation in messages_service.

These tests verify that cache is properly invalidated when hackathon data is modified.
"""
import pytest
from unittest.mock import patch, MagicMock, call
from api.messages.messages_service import (
add_nonprofit_to_hackathon,
remove_nonprofit_from_hackathon,
save_hackathon,
clear_cache
)


class TestCacheInvalidation:
"""Test cases for cache invalidation in hackathon operations."""

@patch('api.messages.messages_service.clear_cache')
@patch('api.messages.messages_service.get_db')
def test_add_nonprofit_to_hackathon_clears_cache(self, mock_db, mock_clear_cache):
"""Test that adding a nonprofit to a hackathon clears the cache."""
# Setup
mock_hackathon_doc = MagicMock()
mock_hackathon_data = MagicMock()
mock_hackathon_data.exists = True
mock_hackathon_data.to_dict.return_value = {"nonprofits": []}
mock_hackathon_doc.get.return_value = mock_hackathon_data

mock_nonprofit_doc = MagicMock()
mock_nonprofit_data = MagicMock()
mock_nonprofit_data.exists = True
mock_nonprofit_doc.get.return_value = mock_nonprofit_data

mock_collection = MagicMock()
mock_collection.document.side_effect = lambda doc_id: (
mock_hackathon_doc if doc_id == "hackathon123" else mock_nonprofit_doc
)
mock_db.return_value.collection.return_value = mock_collection

json_data = {
"hackathonId": "hackathon123",
"nonprofitId": "nonprofit456"
}

# Execute
result = add_nonprofit_to_hackathon(json_data)

# Assert
assert result["message"] == "Nonprofit added to hackathon"
mock_clear_cache.assert_called_once()

@patch('api.messages.messages_service.clear_cache')
@patch('api.messages.messages_service.get_db')
def test_remove_nonprofit_from_hackathon_clears_cache(self, mock_db, mock_clear_cache):
"""Test that removing a nonprofit from a hackathon clears the cache."""
# Setup
mock_nonprofit_ref = MagicMock()
mock_nonprofit_ref.id = "nonprofit456"

mock_hackathon_doc = MagicMock()
mock_hackathon_data = MagicMock()
mock_hackathon_data.to_dict.return_value = {"nonprofits": [mock_nonprofit_ref]}
mock_hackathon_doc.get.return_value = mock_hackathon_data

mock_nonprofit_doc = MagicMock()

mock_collection = MagicMock()
mock_collection.document.side_effect = lambda doc_id: (
mock_hackathon_doc if doc_id == "hackathon123" else mock_nonprofit_doc
)
mock_db.return_value.collection.return_value = mock_collection

json_data = {
"hackathonId": "hackathon123",
"nonprofitId": "nonprofit456"
}

# Execute
result = remove_nonprofit_from_hackathon(json_data)

# Assert
assert result["message"] == "Nonprofit removed from hackathon"
mock_clear_cache.assert_called_once()

@patch('api.messages.messages_service.clear_cache')
@patch('api.messages.messages_service.get_db')
@patch('api.messages.messages_service.validate_hackathon_data')
def test_save_hackathon_clears_cache(self, mock_validate, mock_db, mock_clear_cache):
"""Test that saving a hackathon clears the cache."""
# Setup
mock_db_instance = MagicMock()
mock_db.return_value = mock_db_instance
mock_validate.return_value = None

# Mock transaction
mock_transaction = MagicMock()
mock_db_instance.transaction.return_value = mock_transaction

# Mock collection and document
mock_hackathon_ref = MagicMock()
mock_collection = MagicMock()
mock_collection.document.return_value = mock_hackathon_ref
mock_db_instance.collection.return_value = mock_collection

json_data = {
"title": "Test Hackathon",
"description": "Test Description",
"location": "Test Location",
"start_date": "2024-01-01",
"end_date": "2024-01-02",
"type": "virtual",
"image_url": "https://example.com/image.png",
"event_id": "event123"
}

# Execute
result = save_hackathon(json_data, "user123")

# Assert
assert result.text == "Saved Hackathon"
mock_clear_cache.assert_called_once()

@patch('api.messages.messages_service.doc_to_json')
@patch('api.messages.messages_service.get_single_hackathon_event')
@patch('api.messages.messages_service.get_single_hackathon_id')
@patch('api.messages.messages_service.get_hackathon_list')
def test_clear_cache_clears_all_caches(
self,
mock_get_hackathon_list,
mock_get_single_hackathon_id,
mock_get_single_hackathon_event,
mock_doc_to_json
):
"""Test that clear_cache clears all hackathon-related caches."""
# Execute
clear_cache()

# Assert - verify that cache_clear was called on all cached functions
mock_doc_to_json.cache_clear.assert_called_once()
mock_get_single_hackathon_event.cache_clear.assert_called_once()
mock_get_single_hackathon_id.cache_clear.assert_called_once()
mock_get_hackathon_list.cache_clear.assert_called_once()
7 changes: 6 additions & 1 deletion services/problem_statements_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,12 @@ def update_problem_statement_fields(d):
if problem_statement is not None:
problem_statement.update(d)
problem_statement.id = d['id']
return update_problem_statement(problem_statement)
result = update_problem_statement(problem_statement)

# Clear cache after updating problem statement
get_problem_statement.cache_clear()

return result
else:
return None

Expand Down