-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: /delete command for clear messages | resolve #25 #31
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,11 +24,11 @@ defmodule SaveIt.Migration.Typesense do | |
Typesense.handle_response!(res) | ||
end | ||
|
||
def delete_collection!(collection_name) do | ||
def delete_collection(collection_name) do | ||
req = build_request("/collections/#{collection_name}") | ||
res = Req.delete!(req) | ||
res = Req.delete(req) | ||
|
||
Typesense.handle_response!(res) | ||
Typesense.handle_response(res) | ||
Comment on lines
+27
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Error handling mismatch detected in caller The
Example fix for the first approach: def drop_photos!() do
case Typesense.delete_collection(@collection_name) do
{:ok, response} -> response
{:error, reason} -> raise "Failed to drop photos collection: #{inspect(reason)}"
end
end 🔗 Analysis chainLGTM! Consistent error handling approach. The change from bang (!) to non-bang methods is consistent throughout the function, making error handling more graceful. Let's verify the impact on callers of this function: Consider adding @doc """
Deletes a Typesense collection.
Returns {:ok, response} on success or {:error, reason} on failure.
"""
@spec delete_collection(String.t()) :: {:ok, map()} | {:error, any()} 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Find all callers of delete_collection to ensure they handle the new error cases
rg -A 3 "delete_collection" --type elixir
Length of output: 553 Script: #!/bin/bash
# Let's check the implementation of reset! in photo.ex to understand how it handles the response
rg -B 2 -A 5 "reset!" lib/save_it/migration/typesense/photo.ex
Length of output: 178 Script: #!/bin/bash
# Let's also check if there are any other files that might be using similar patterns
ast-grep --pattern 'def reset!() do
$$$
end'
Length of output: 371 Script: #!/bin/bash
# Let's see the full content of photo.ex to understand the context
cat lib/save_it/migration/typesense/photo.ex
Length of output: 2012 |
||
end | ||
|
||
defp get_env() do | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,7 +37,8 @@ defmodule SaveIt.Migration.Typesense.Photo do | |
|
||
Typesense.update_collection!(@collection_name, %{ | ||
"fields" => [ | ||
%{"name" => "file_id", "type" => "string", "optional" => true} | ||
%{"name" => "file_id", "type" => "string", "optional" => true}, | ||
%{"name" => "url", "drop" => true} | ||
] | ||
}) | ||
end | ||
|
@@ -66,12 +67,12 @@ defmodule SaveIt.Migration.Typesense.Photo do | |
Logger.info("migrated #{count} photos") | ||
end | ||
|
||
def drop_photos!() do | ||
Typesense.delete_collection!(@collection_name) | ||
def drop_photos() do | ||
Typesense.delete_collection(@collection_name) | ||
end | ||
|
||
def reset!() do | ||
drop_photos!() | ||
drop_photos() | ||
create_photos_20241024!() | ||
migrate_photos_20241029!() | ||
Comment on lines
+75
to
77
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider making reset operations atomic. The Consider implementing a more robust reset operation: def reset!() do
- drop_photos()
- create_photos_20241024!()
- migrate_photos_20241029!()
+ with :ok <- drop_photos(),
+ :ok <- create_photos_20241024!(),
+ :ok <- migrate_photos_20241029!() do
+ :ok
+ else
+ error ->
+ Logger.error("Reset failed: #{inspect(error)}")
+ error
+ end
end
|
||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,14 @@ defmodule SaveIt.PhotoService do | |
end | ||
end | ||
|
||
def delete_photo(file_id) do | ||
Typesense.delete_document_by_query("photos", "file_id:[#{file_id}]") | ||
end | ||
|
||
def delete_photos(file_ids) do | ||
Typesense.delete_document_by_query("photos", "file_id:[#{Enum.join(file_ids, ",")}]") | ||
end | ||
Comment on lines
+43
to
+45
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Improve bulk deletion implementation The bulk deletion function needs several improvements for robustness and safety:
- def delete_photos(file_ids) do
+ def delete_photos!(file_ids) when is_list(file_ids) do
+ unless Enum.all?(file_ids, &is_binary/1) do
+ raise ArgumentError, "All file_ids must be strings"
+ end
+
+ if length(file_ids) > 100 do
+ Logger.warn("Attempting to delete #{length(file_ids)} photos at once")
+ end
+
+ result = Typesense.delete_document_by_query(
+ "photos",
+ "file_id:[#{Enum.join(file_ids, ",")}]"
+ )
+
+ case result do
+ {:ok, response} -> response
+ {:error, error} -> raise "Failed to delete photos: #{inspect(error)}"
+ end
end Consider implementing batch processing for large lists to avoid potential timeouts or performance issues: def delete_photos_in_batches!(file_ids, batch_size \\ 100) do
file_ids
|> Enum.chunk_every(batch_size)
|> Enum.map(&delete_photos!/1)
end |
||
|
||
def get_photo(photo_id) do | ||
Typesense.get_document("photos", photo_id) | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,13 +63,23 @@ defmodule SmallSdk.Typesense do | |
handle_response(res) | ||
end | ||
|
||
def delete_document!(collection_name, document_id) do | ||
def delete_document(collection_name, document_id) do | ||
req = build_request("/collections/#{collection_name}/documents/#{document_id}") | ||
res = Req.delete(req) | ||
|
||
handle_response(res) | ||
end | ||
|
||
# docs: https://typesense.org/docs/27.1/api/documents.html#delete-documents | ||
def delete_document_by_query(collection_name, filter_by, opts \\ []) do | ||
batch_size = Keyword.get(opts, :batch_size, 100) | ||
|
||
req = build_request("/collections/#{collection_name}/documents") | ||
|
||
Req.delete(req, params: %{"filter_by" => filter_by, "batch_size" => batch_size}) | ||
|> handle_response() | ||
end | ||
Comment on lines
+73
to
+81
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add validation and improve error handling for batch deletions. While the implementation follows the Typesense API, there are several areas for improvement:
Consider these improvements: # docs: https://typesense.org/docs/27.1/api/documents.html#delete-documents
+@doc """
+Deletes documents matching the given filter query.
+
+## Parameters
+ - collection_name: The name of the collection
+ - filter_by: Filter query in Typesense syntax (e.g., "user_id:=1234")
+ - opts: Keyword list of options
+ - batch_size: Number of documents to delete per batch (default: 100)
+
+## Examples
+ delete_document_by_query("photos", "user_id:=1234")
+ delete_document_by_query("photos", "created_at:<1234567890", batch_size: 50)
+"""
def delete_document_by_query(collection_name, filter_by, opts \\ []) do
+ unless is_binary(filter_by) and filter_by != "" do
+ raise ArgumentError, "filter_by must be a non-empty string"
+ end
+
batch_size = Keyword.get(opts, :batch_size, 100)
req = build_request("/collections/#{collection_name}/documents")
-
- Req.delete(req, params: %{"filter_by" => filter_by, "batch_size" => batch_size})
- |> handle_response()
+ case Req.delete(req, params: %{"filter_by" => filter_by, "batch_size" => batch_size}) do
+ {:ok, %{status: status} = response} when status in 200..299 ->
+ response
+ |> handle_response()
+ |> Map.get("num_deleted", 0)
+ error ->
+ Logger.error("Batch deletion failed: #{inspect(error)}")
+ handle_response(error)
+ end
end For large collections, consider adding progress tracking: # Add this helper function
defp log_deletion_progress(deleted, total) do
Logger.info("Deleted #{deleted} out of #{total} documents (#{round(deleted/total * 100)}%)")
end For very large collections, consider implementing this as a background job with progress tracking and the ability to resume on failure. |
||
|
||
def create_search_key() do | ||
{url, _} = get_env() | ||
req = build_request("/keys") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
# mix run priv/typesense/2024-10-29_photos_url_to_file_id.ex | ||
SaveIt.Migration.Typesense.Photo.migrate_photos_20241029!() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance error handling and message deletion order.
The current implementation has several areas for improvement: