# XACKDEL

> Acknowledge and delete stream entries atomically.

The `XACKDEL` command acknowledges and deletes stream entries atomically in a single operation. This is useful for consumer groups where you want to acknowledge message processing and remove the entries from the stream simultaneously.

## Arguments

<ParamField body="key" type="str" required>
  The key of the stream.
</ParamField>

<ParamField body="group" type="str" required>
  The consumer group name.
</ParamField>

<ParamField body="ids" type="*List[str]" required>
  One or more stream entry IDs to acknowledge and delete.
</ParamField>

<ParamField body="option" type="Literal['KEEPREF', 'DELREF', 'ACKED', 'keepref', 'delref', 'acked']">
  Optional deletion behavior (case-insensitive):
  - `KEEPREF` or `keepref`: Keep consumer group references
  - `DELREF` or `delref`: Delete consumer group references
  - `ACKED` or `acked`: Only acknowledge messages (don't delete)
</ParamField>

## Response

<ResponseField type="List[int]" required>
  A list of integers indicating the result for each ID in the same order as provided.
</ResponseField>

<RequestExample>
```py Single Entry
# Acknowledge and delete a single entry
result = redis.xackdel("mystream", "mygroup", "1638360173533-0")
print(result)  # List of results for each ID
```

```py Multiple Entries
# Acknowledge and delete multiple entries
result = redis.xackdel(
    "mystream",
    "mygroup",
    "1638360173533-0",
    "1638360173533-1",
    "1638360173533-2"
)
print(result)  # List of results for each ID
```

```py With KEEPREF Option
# Keep consumer group references when deleting entries
# Useful when you want to delete entries but maintain group tracking
result = redis.xackdel(
    "mystream",
    "mygroup",
    "1638360173533-0",
    "1638360173533-1",
    option="KEEPREF"
)
print(result)  # List of results for each ID
```

```py With DELREF Option
# Delete consumer group references along with entries
# Useful for complete cleanup of processed messages
result = redis.xackdel(
    "mystream",
    "mygroup",
    "1638360173533-0",
    "1638360173533-1",
    option="DELREF"
)
print(result)  # List of results for each ID
```

```py With ACKED Option
# Only acknowledge messages without deleting them
# Useful when you want to mark as processed but keep for audit/debugging
result = redis.xackdel(
    "mystream",
    "mygroup",
    "1638360173533-0",
    option="ACKED"
)
print(result)  # List of results for each ID
# Entry remains in stream but is acknowledged
```

```py Consumer Group Processing
# Create a consumer group
redis.xgroup_create("orders", "processors", "0", mkstream=True)

# Add some orders to the stream
redis.xadd("orders", "*", {"order_id": "123", "status": "pending"})
redis.xadd("orders", "*", {"order_id": "124", "status": "pending"})

# Read messages as a consumer
messages = redis.xreadgroup(
    "processors", "consumer1", {"orders": ">"},
    count=2
)

# Process messages and acknowledge + delete them
for stream_name, entries in messages:
    for entry_id, fields in entries:
        # Process the order...
        print(f"Processing order {fields['order_id']}")
        
        # Acknowledge and delete the entry (default behavior)
        redis.xackdel("orders", "processors", entry_id)
        
        # Or use DELREF for complete cleanup
        # redis.xackdel("orders", "processors", entry_id, option="DELREF")
```

```py Batch Processing
# Read pending messages
pending = redis.xreadgroup(
    "tasks", "worker1", {"task-queue": ">"},
    count=10
)

if pending:
    stream_name, entries = pending[0]
    processed_ids = []
    
    # Process each task
    for entry_id, fields in entries:
        try:
            # Process task...
            print(f"Processing task {entry_id}")
            processed_ids.append(entry_id)
        except Exception as error:
            print(f"Failed to process {entry_id}: {error}")
    
    # Acknowledge and delete all successfully processed tasks
    # Using DELREF to completely remove references
    if processed_ids:
        result = redis.xackdel("task-queue", "tasks", *processed_ids, option="DELREF")
        print(f"Results: {result}")  # List of results for each ID
```

```py Audit Mode with ACKED
# Process messages but keep them for audit/debugging purposes
messages = redis.xreadgroup(
    "audit", "auditor1", {"events": ">"},
    count=5
)

for stream_name, entries in messages:
    entry_ids = [entry_id for entry_id, _ in entries]
    
    # Process and acknowledge but don't delete
    for entry_id, fields in entries:
        # Audit the event...
        print(f"Auditing event {fields}")
    
    # Acknowledge without deleting (keep for audit trail)
    result = redis.xackdel("events", "audit", *entry_ids, option="ACKED")
    print(f"Acknowledged {len(result)} events (kept in stream)")
```
</RequestExample>

## Use Cases

- **Message Queue Cleanup**: Process messages and remove them from the stream in one operation
- **Event Processing**: Acknowledge event handling and clean up the stream
- **Task Queue Management**: Complete tasks and remove them atomically
- **Memory Optimization**: Reduce stream memory usage by removing processed entries

## Comparison with XACK + XDEL

Traditional approach (two operations):
```py
# Acknowledge the message
redis.xack("mystream", "mygroup", "123-0")
# Then delete it
redis.xdel("mystream", "123-0")
```

With XACKDEL (single atomic operation):
```py
# Acknowledge and delete in one operation (default)
redis.xackdel("mystream", "mygroup", "123-0")

# With options for fine-grained control
redis.xackdel("mystream", "mygroup", "123-0", option="DELREF")  # Complete cleanup
redis.xackdel("mystream", "mygroup", "123-0", option="ACKED")   # Acknowledge only
```

<Note>
This command is available in Redis 8.2.0 and later. It combines XACK and XDEL into a single atomic operation, which is more efficient and ensures consistency.
</Note>
