@@ -3381,8 +3381,10 @@ async def index_google_gmail_messages(
33813381 connector_id : int ,
33823382 search_space_id : int ,
33833383 user_id : str ,
3384+ start_date : str | None = None ,
3385+ end_date : str | None = None ,
3386+ update_last_indexed : bool = True ,
33843387 max_messages : int = 100 ,
3385- days_back : int = 30 ,
33863388) -> tuple [int , str ]:
33873389 """
33883390 Index Gmail messages for a specific connector.
@@ -3392,14 +3394,24 @@ async def index_google_gmail_messages(
33923394 connector_id: ID of the Gmail connector
33933395 search_space_id: ID of the search space
33943396 user_id: ID of the user
3397+ start_date: Start date for filtering messages (YYYY-MM-DD format)
3398+ end_date: End date for filtering messages (YYYY-MM-DD format)
3399+ update_last_indexed: Whether to update the last_indexed_at timestamp (default: True)
33953400 max_messages: Maximum number of messages to fetch (default: 100)
3396- days_back: Number of days to look back (default: 30)
33973401
33983402 Returns:
33993403 Tuple of (number_of_indexed_messages, status_message)
34003404 """
34013405 task_logger = TaskLoggingService (session , search_space_id )
34023406
3407+ # Calculate days back based on start_date
3408+ if start_date :
3409+ try :
3410+ start_date_obj = datetime .strptime (start_date , "%Y-%m-%d" )
3411+ days_back = (datetime .now () - start_date_obj ).days
3412+ except ValueError :
3413+ days_back = 30 # Default to 30 days if start_date is invalid
3414+
34033415 # Log task start
34043416 log_entry = await task_logger .log_task_start (
34053417 task_name = "google_gmail_messages_indexing" ,
@@ -3426,8 +3438,8 @@ async def index_google_gmail_messages(
34263438
34273439 if not connector :
34283440 error_msg = f"Gmail connector with ID { connector_id } not found"
3429- await task_logger .log_task_completion (
3430- log_entry . id , "FAILED" , error_msg , {"error_type" : "ConnectorNotFound" }
3441+ await task_logger .log_task_failure (
3442+ log_entry , error_msg , {"error_type" : "ConnectorNotFound" }
34313443 )
34323444 return 0 , error_msg
34333445
@@ -3442,31 +3454,53 @@ async def index_google_gmail_messages(
34423454 scopes = config_data .get ("scopes" , []),
34433455 )
34443456
3445- # Initialize Gmail connector
3457+ if (
3458+ not credentials .client_id
3459+ or not credentials .client_secret
3460+ or not credentials .refresh_token
3461+ ):
3462+ await task_logger .log_task_failure (
3463+ log_entry ,
3464+ f"Google gmail credentials not found in connector config for connector { connector_id } " ,
3465+ "Missing Google gmail credentials" ,
3466+ {"error_type" : "MissingCredentials" },
3467+ )
3468+ return 0 , "Google gmail credentials not found in connector config"
3469+
3470+ # Initialize Google gmail client
3471+ await task_logger .log_task_progress (
3472+ log_entry ,
3473+ f"Initializing Google gmail client for connector { connector_id } " ,
3474+ {"stage" : "client_initialization" },
3475+ )
3476+
3477+ # Initialize Google gmail connector
34463478 gmail_connector = GoogleGmailConnector (credentials )
34473479
3448- # Fetch recent messages
3449- logger .info (f"Fetching recent Gmail messages for connector { connector_id } " )
3480+ # Fetch recent Google gmail messages
3481+ logger .info (f"Fetching recent emails for connector { connector_id } " )
34503482 messages , error = gmail_connector .get_recent_messages (
34513483 max_results = max_messages , days_back = days_back
34523484 )
34533485
34543486 if error :
3455- await task_logger .log_task_completion (
3456- log_entry . id , "FAILED" , f"Failed to fetch messages: { error } " , {}
3487+ await task_logger .log_task_failure (
3488+ log_entry , f"Failed to fetch messages: { error } " , {}
34573489 )
34583490 return 0 , f"Failed to fetch Gmail messages: { error } "
34593491
34603492 if not messages :
3461- success_msg = "No Gmail messages found in the specified date range"
3462- await task_logger .log_task_completion (
3463- log_entry . id , "SUCCESS" , success_msg , {"messages_count" : 0 }
3493+ success_msg = "No Google gmail messages found in the specified date range"
3494+ await task_logger .log_task_success (
3495+ log_entry , success_msg , {"messages_count" : 0 }
34643496 )
34653497 return 0 , success_msg
34663498
3467- logger .info (f"Found { len (messages )} Gmail messages to index" )
3499+ logger .info (f"Found { len (messages )} Google gmail messages to index" )
34683500
3469- indexed_count = 0
3501+ documents_indexed = 0
3502+ skipped_messages = []
3503+ documents_skipped = 0
34703504 for message in messages :
34713505 try :
34723506 # Extract message information
@@ -3491,22 +3525,57 @@ async def index_google_gmail_messages(
34913525 elif name == "date" :
34923526 date_str = value
34933527
3528+ if not message_id :
3529+ logger .warning (f"Skipping message with missing ID: { subject } " )
3530+ skipped_messages .append (f"{ subject } (missing ID)" )
3531+ documents_skipped += 1
3532+ continue
3533+
3534+ # Format message to markdown
3535+ markdown_content = gmail_connector .format_message_to_markdown (message )
3536+
3537+ if not markdown_content .strip ():
3538+ logger .warning (f"Skipping message with no content: { subject } " )
3539+ skipped_messages .append (f"{ subject } (no content)" )
3540+ documents_skipped += 1
3541+ continue
3542+
3543+ # Create a simple summary
3544+ summary_content = f"Google Gmail Message: { subject } \n \n "
3545+ summary_content += f"Sender: { sender } \n "
3546+ summary_content += f"Date: { date_str } \n "
3547+
3548+ # Generate content hash
3549+ content_hash = generate_content_hash (markdown_content , search_space_id )
3550+
34943551 # Check if document already exists
3495- existing_doc_result = await session .execute (
3496- select (Document ).filter (
3497- Document .search_space_id == search_space_id ,
3498- Document .document_type == DocumentType .GOOGLE_GMAIL_CONNECTOR ,
3499- Document .document_metadata ["message_id" ].astext == message_id ,
3500- )
3552+ existing_doc_by_hash_result = await session .execute (
3553+ select (Document ).where (Document .content_hash == content_hash )
3554+ )
3555+ existing_document_by_hash = (
3556+ existing_doc_by_hash_result .scalars ().first ()
35013557 )
3502- existing_doc = existing_doc_result .scalars ().first ()
35033558
3504- if existing_doc :
3505- logger .info (f"Gmail message { message_id } already indexed, skipping" )
3559+ if existing_document_by_hash :
3560+ logger .info (
3561+ f"Document with content hash { content_hash } already exists for message { message_id } . Skipping processing."
3562+ )
3563+ documents_skipped += 1
35063564 continue
35073565
3508- # Format message to markdown
3509- markdown_content = gmail_connector .format_message_to_markdown (message )
3566+ # Generate embedding for the summary
3567+ summary_embedding = config .embedding_model_instance .embed (
3568+ summary_content
3569+ )
3570+
3571+ # Process chunks
3572+ chunks = [
3573+ Chunk (
3574+ content = chunk .text ,
3575+ embedding = config .embedding_model_instance .embed (chunk .text ),
3576+ )
3577+ for chunk in config .chunker_instance .chunk (markdown_content )
3578+ ]
35103579
35113580 # Create and store new document
35123581 logger .info (f"Creating new document for Gmail message: { subject } " )
@@ -3523,56 +3592,72 @@ async def index_google_gmail_messages(
35233592 "connector_id" : connector_id ,
35243593 },
35253594 content = markdown_content ,
3595+ content_hash = content_hash ,
3596+ embedding = summary_embedding ,
3597+ chunks = chunks ,
35263598 )
35273599 session .add (document )
3528- await session .flush ()
3529-
3530- # Create chunks for the document
3531- chunks = config .chunker_instance .chunk (markdown_content )
3532- for i , chunk_text in enumerate (chunks ):
3533- chunk = Chunk (
3534- document_id = document .id ,
3535- content = chunk_text ,
3536- chunk_index = i ,
3537- embedding = config .embedding_model_instance .embed_query (
3538- chunk_text
3539- ),
3540- )
3541- session .add (chunk )
3542-
3543- indexed_count += 1
3544- logger .info (f"Successfully indexed Gmail message: { subject } " )
3600+ documents_indexed += 1
3601+ logger .info (f"Successfully indexed new email { summary_content } " )
35453602
35463603 except Exception as e :
35473604 logger .error (
3548- f"Error indexing Gmail message { message_id } : { e !s} " , exc_info = True
3605+ f"Error processing the email { message_id } : { e !s} " ,
3606+ exc_info = True ,
35493607 )
3550- continue
3608+ skipped_messages .append (f"{ subject } (processing error)" )
3609+ documents_skipped += 1
3610+ continue # Skip this message and continue with others
3611+
3612+ # Update the last_indexed_at timestamp for the connector only if requested
3613+ total_processed = documents_indexed
3614+ if update_last_indexed :
3615+ connector .last_indexed_at = datetime .now ()
3616+ logger .info (f"Updated last_indexed_at to { connector .last_indexed_at } " )
35513617
35523618 # Commit all changes
35533619 await session .commit ()
3620+ logger .info (
3621+ "Successfully committed all Google gmail document changes to database"
3622+ )
35543623
3555- # Update connector's last_indexed_at timestamp
3556- connector .last_indexed_at = datetime .now (UTC )
3557- await session .commit ()
3624+ # Log success
3625+ await task_logger .log_task_success (
3626+ log_entry ,
3627+ f"Successfully completed Google gmail indexing for connector { connector_id } " ,
3628+ {
3629+ "events_processed" : total_processed ,
3630+ "documents_indexed" : documents_indexed ,
3631+ "documents_skipped" : documents_skipped ,
3632+ "skipped_messages_count" : len (skipped_messages ),
3633+ },
3634+ )
35583635
3559- success_msg = f"Successfully indexed { indexed_count } Gmail messages"
3560- await task_logger .log_task_completion (
3561- log_entry .id ,
3562- "SUCCESS" ,
3563- success_msg ,
3564- {"indexed_count" : indexed_count , "total_messages" : len (messages )},
3636+ logger .info (
3637+ f"Google gmail indexing completed: { documents_indexed } new emails, { documents_skipped } skipped"
35653638 )
3566- logger .info (success_msg )
3567- return indexed_count , success_msg
3639+ return (
3640+ total_processed ,
3641+ None ,
3642+ ) # Return None as the error message to indicate success
35683643
3644+ except SQLAlchemyError as db_error :
3645+ await session .rollback ()
3646+ await task_logger .log_task_failure (
3647+ log_entry ,
3648+ f"Database error during Google gmail indexing for connector { connector_id } " ,
3649+ str (db_error ),
3650+ {"error_type" : "SQLAlchemyError" },
3651+ )
3652+ logger .error (f"Database error: { db_error !s} " , exc_info = True )
3653+ return 0 , f"Database error: { db_error !s} "
35693654 except Exception as e :
3570- await task_logger . log_task_completion (
3571- log_entry . id ,
3572- "FAILED" ,
3573- f"Failed to index Gmail messages for connector { connector_id } " ,
3655+ await session . rollback ()
3656+ await task_logger . log_task_failure (
3657+ log_entry ,
3658+ f"Failed to index Google gmail emails for connector { connector_id } " ,
35743659 str (e ),
35753660 {"error_type" : type (e ).__name__ },
35763661 )
3577- logger .error (f"Failed to index Gmail messages : { e !s} " , exc_info = True )
3578- return 0 , f"Failed to index Gmail messages : { e !s} "
3662+ logger .error (f"Failed to index Google gmail emails : { e !s} " , exc_info = True )
3663+ return 0 , f"Failed to index Google gmail emails : { e !s} "
0 commit comments