-
Notifications
You must be signed in to change notification settings - Fork 1
放弃在 save_it bot 添加 notes 功能,保持 save_it 简单 #22
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
Changes from 3 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 |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# 2024-10-25 | ||
|
||
## Req call typesense API alway :timeout, but typesense was updated. | ||
|
||
```elixir | ||
** (MatchError) no match of right hand side value: {:error, %Req.TransportError{reason: :timeout}} | ||
(save_it 0.2.0-rc.1) lib/migration/typesense.ex:11: Migration.Typesense.create_collection!/1 | ||
priv/typesense/reset.exs:3: (file) | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Typesense | ||
|
||
## Typesense API Errors | ||
|
||
``` | ||
# 400 Bad Request - The request could not be understood due to malformed syntax. | ||
# 401 Unauthorized - Your API key is wrong. | ||
# 404 Not Found - The requested resource is not found. | ||
# 409 Conflict - When a resource already exists. | ||
# 422 Unprocessable Entity - Request is well-formed, but cannot be processed. | ||
# 503 Service Unavailable - We’re temporarily offline. Please try again later. | ||
``` | ||
|
||
docs: https://typesense.org/docs/27.1/api/api-errors.html#api-errors |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,42 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
defmodule Migration.Typesense do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def create_collection!(schema) do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
req = build_request("/collections") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{:ok, res} = Req.post(req, json: schema) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
res.body | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+2
to
+7
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. Add error handling and documentation for create_collection!. The function needs better error handling and documentation:
Consider this improvement: + @doc """
+ Creates a new collection in Typesense with the given schema.
+
+ ## Parameters
+ - schema: Map containing the collection schema definition
+
+ ## Returns
+ - Map containing the created collection details
+
+ ## Raises
+ - RuntimeError if the collection creation fails
+ """
def create_collection!(schema) do
+ unless is_map(schema), do: raise ArgumentError, "schema must be a map"
+
req = build_request("/collections")
- {:ok, res} = Req.post(req, json: schema)
+ case Req.post(req, json: schema) do
+ {:ok, res} when res.status in 200..299 -> res.body
+ {:ok, res} -> raise "Failed to create collection: #{inspect(res.body)}"
+ {:error, error} -> raise "Request failed: #{inspect(error)}"
+ end
-
- res.body
end 📝 Committable suggestion
Suggested change
Comment on lines
+2
to
+7
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. Add proper error handling and documentation for public functions. The public API functions have several areas for improvement:
Here's a suggested improvement: + @doc """
+ Creates a new collection in Typesense.
+
+ ## Parameters
+ - schema: Map containing the collection schema
+
+ ## Returns
+ - {:ok, response} on success
+ - {:error, reason} on failure
+ """
+ @spec create_collection!(map()) :: {:ok, map()} | {:error, any()}
def create_collection!(schema) do
+ with {:ok, schema} <- validate_schema(schema),
+ req <- build_request("/collections"),
+ {:ok, res} <- Req.post(req, json: schema) do
+ {:ok, res.body}
+ else
+ {:error, reason} -> {:error, reason}
+ error -> {:error, error}
+ end
end
+ @doc """
+ Deletes a collection from Typesense.
+
+ ## Parameters
+ - collection_name: String name of the collection
+
+ ## Returns
+ - {:ok, response} on success
+ - {:error, reason} on failure
+ """
+ @spec delete_collection!(String.t()) :: {:ok, map()} | {:error, any()}
def delete_collection!(collection_name) do
+ with {:ok, name} <- validate_collection_name(collection_name),
+ req <- build_request("/collections/#{name}"),
+ {:ok, res} <- Req.delete(req) do
+ {:ok, res.body}
+ else
+ {:error, reason} -> {:error, reason}
+ error -> {:error, error}
+ end
end Add these private validation functions: defp validate_schema(%{} = schema) do
{:ok, schema}
end
defp validate_schema(_), do: {:error, "Invalid schema format"}
defp validate_collection_name(name) when is_binary(name) and byte_size(name) > 0 do
{:ok, name}
end
defp validate_collection_name(_), do: {:error, "Invalid collection name"} Also applies to: 9-14, 16-21 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def delete_collection!(collection_name) do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
req = build_request("/collections/#{collection_name}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{:ok, res} = Req.delete(req) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
res.body | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def list_collections() do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
req = build_request("/collections") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{:ok, res} = Req.get(req) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
res.body | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+9
to
+21
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 error handling and documentation for delete_collection! and list_collections. Both functions need similar improvements as create_collection!:
Apply these improvements: + @doc """
+ Deletes a collection from Typesense by name.
+
+ ## Parameters
+ - collection_name: String name of the collection to delete
+
+ ## Raises
+ - ArgumentError if collection_name is invalid
+ - RuntimeError if the deletion fails
+ """
def delete_collection!(collection_name) do
+ unless is_binary(collection_name) and collection_name != "",
+ do: raise ArgumentError, "collection_name must be a non-empty string"
+
req = build_request("/collections/#{collection_name}")
- {:ok, res} = Req.delete(req)
-
- res.body
+ case Req.delete(req) do
+ {:ok, res} when res.status in 200..299 -> res.body
+ {:ok, res} -> raise "Failed to delete collection: #{inspect(res.body)}"
+ {:error, error} -> raise "Request failed: #{inspect(error)}"
+ end
end
+ @doc """
+ Lists all collections in Typesense.
+
+ ## Returns
+ - List of collection details
+
+ ## Raises
+ - RuntimeError if the request fails
+ """
def list_collections() do
req = build_request("/collections")
- {:ok, res} = Req.get(req)
-
- res.body
+ case Req.get(req) do
+ {:ok, res} when res.status in 200..299 -> res.body
+ {:ok, res} -> raise "Failed to list collections: #{inspect(res.body)}"
+ {:error, error} -> raise "Request failed: #{inspect(error)}"
+ end
end 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
defp get_env() do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
url = Application.fetch_env!(:save_it, :typesense_url) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
api_key = Application.fetch_env!(:save_it, :typesense_api_key) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{url, api_key} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+23
to
+28
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 safer environment variable handling. The Consider using defp get_env() do
- url = Application.fetch_env!(:save_it, :typesense_url)
- api_key = Application.fetch_env!(:save_it, :typesense_api_key)
-
- {url, api_key}
+ with {:ok, url} <- get_config(:typesense_url),
+ {:ok, api_key} <- get_config(:typesense_api_key) do
+ {:ok, {url, api_key}}
+ end
end
+ defp get_config(key) do
+ case Application.get_env(:save_it, key) do
+ nil -> {:error, "Missing configuration: #{key}"}
+ value when byte_size(value) > 0 -> {:ok, value}
+ _ -> {:error, "Invalid configuration: #{key}"}
+ end
+ end
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
defp build_request(path) do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{url, api_key} = get_env() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Req.new( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
base_url: url, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
url: path, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
headers: [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{"Content-Type", "application/json"}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{"X-TYPESENSE-API-KEY", api_key} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+23
to
+41
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. Enhance helper functions for better error handling and security. The helper functions need improvements:
Consider these improvements: defp get_env() do
- url = Application.fetch_env!(:save_it, :typesense_url)
- api_key = Application.fetch_env!(:save_it, :typesense_api_key)
+ url = case Application.fetch_env(:save_it, :typesense_url) do
+ {:ok, value} when is_binary(value) and value != "" -> value
+ _ -> raise "Missing or invalid :typesense_url configuration"
+ end
+
+ api_key = case Application.fetch_env(:save_it, :typesense_api_key) do
+ {:ok, value} when is_binary(value) and value != "" -> value
+ _ -> raise "Missing or invalid :typesense_api_key configuration"
+ end
{url, api_key}
end
defp build_request(path) do
{url, api_key} = get_env()
+ encoded_path = URI.encode(path)
Req.new(
base_url: url,
- url: path,
+ url: encoded_path,
headers: [
{"Content-Type", "application/json"},
{"X-TYPESENSE-API-KEY", api_key}
]
)
end 📝 Committable suggestion
Suggested change
Comment on lines
+30
to
+41
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 request timeout configuration and consider making headers configurable. The request configuration could be improved with timeout settings and more flexible header configuration. Consider these improvements: defp build_request(path) do
- {url, api_key} = get_env()
+ with {:ok, {url, api_key}} <- get_env() do
+ Req.new(
+ base_url: url,
+ url: path,
+ headers: build_headers(api_key),
+ connect_options: [timeout: get_timeout()],
+ retry: :transient
+ )
+ end
end
+ defp build_headers(api_key) do
+ [
+ {"Content-Type", "application/json"},
+ {"X-TYPESENSE-API-KEY", api_key}
+ ]
+ end
+ defp get_timeout do
+ Application.get_env(:save_it, :typesense_timeout, 5000)
+ end 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,30 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
defmodule Migration.Typesense.Note do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
alias Migration.Typesense | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@notes_schema %{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"name" => "notes", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"fields" => [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# TODO: 第一步先实现文本,今后再考虑图片 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
%{"name" => "content", "type" => "string"}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# references photos.id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# note: 抉择:这个 app 核心是给予图片的视觉笔记,暂时不考虑单独 text 的笔记 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# %{"name" => "photo_id", "type" => "string"}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# note: 既然不能实现 RDB reference,那么就直接存储 file_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
%{"name" => "message_id", "type" => "string"}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
%{"name" => "file_id", "type" => "string"}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
%{"name" => "belongs_to_id", "type" => "string"}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
%{"name" => "inserted_at", "type" => "int64"}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
%{"name" => "updated_at", "type" => "int64"} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"default_sorting_field" => "inserted_at" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+4
to
+20
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 Consider schema optimizations and documentation improvements. A few suggestions to improve the schema:
Here's a suggested refactor: + @moduledoc """
+ Manages the Typesense collection for notes.
+ Notes are primarily associated with images and include text content.
+ """
+ @typedoc """
+ Schema for the notes collection:
+ - content: The text content of the note
+ - message_id: Reference to the message containing the note
+ - file_id: Reference to the associated file/image
+ - belongs_to_id: Owner reference
+ - inserted_at: Creation timestamp
+ - updated_at: Last modification timestamp
+ """
@notes_schema %{
- "name" => "notes",
- "fields" => [
+ name: :notes,
+ fields: [
%{"name" => "content", "type" => "string"},
%{"name" => "message_id", "type" => "string"},
%{"name" => "file_id", "type" => "string"},
%{"name" => "belongs_to_id", "type" => "string"},
%{"name" => "inserted_at", "type" => "int64"},
%{"name" => "updated_at", "type" => "int64"}
],
- "default_sorting_field" => "inserted_at"
+ default_sorting_field: :inserted_at
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def create_collection!() do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Typesense.create_collection!(@notes_schema) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def reset!() do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Typesense.delete_collection!(@notes_schema["name"]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Typesense.create_collection!(@notes_schema) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+22
to
+29
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. Add error handling and documentation for public functions. The current implementation could benefit from:
Here's a suggested implementation: + @doc """
+ Creates a new notes collection in Typesense.
+ Raises an error if the collection already exists.
+ """
def create_collection!() do
Typesense.create_collection!(@notes_schema)
end
+ @doc """
+ Resets the notes collection by deleting and recreating it.
+ Raises an error if either operation fails.
+ """
def reset!() do
+ with :ok <- Typesense.delete_collection!(@notes_schema["name"]),
+ :ok <- Typesense.create_collection!(@notes_schema) do
+ :ok
+ else
+ error ->
+ # Log the error and re-raise
+ require Logger
+ Logger.error("Failed to reset notes collection: #{inspect(error)}")
+ raise "Failed to reset notes collection"
+ end
- Typesense.delete_collection!(@notes_schema["name"])
- Typesense.create_collection!(@notes_schema)
end
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,35 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
defmodule Migration.Typesense.Photo do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
alias Migration.Typesense | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@photos_schema %{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"name" => "photos", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"fields" => [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# image: base64 encoded string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
%{"name" => "image", "type" => "image", "store" => false}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
%{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"name" => "image_embedding", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"type" => "float[]", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"embed" => %{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"from" => ["image"], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"model_config" => %{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"model_name" => "ts/clip-vit-b-p32" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
%{"name" => "caption", "type" => "string", "optional" => true, "facet" => false}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
%{"name" => "file_id", "type" => "string"}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
%{"name" => "belongs_to_id", "type" => "string"}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
%{"name" => "inserted_at", "type" => "int64"} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"default_sorting_field" => "inserted_at" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def create_collection!() do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Typesense.create_collection!(@photos_schema) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def reset!() do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Typesense.delete_collection!(@photos_schema["name"]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Typesense.create_collection!(@photos_schema) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+27
to
+34
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. Add documentation and error handling. The public functions need:
Consider this improvement: + @doc """
+ Creates a new photos collection in Typesense.
+
+ Returns `:ok` on success, or raises an error if the collection already exists
+ or if there's a connection issue.
+ """
+ @spec create_collection!() :: :ok | no_return()
def create_collection!() do
- Typesense.create_collection!(@photos_schema)
+ case Typesense.create_collection!(@photos_schema) do
+ {:ok, _} -> :ok
+ {:error, %{"message" => message}} -> raise "Failed to create collection: #{message}"
+ end
end
+ @doc """
+ Resets the photos collection by deleting and recreating it.
+
+ Returns `:ok` on success, or raises an error if the operations fail.
+ """
+ @spec reset!() :: :ok | no_return()
def reset!() do
- Typesense.delete_collection!(@photos_schema["name"])
- Typesense.create_collection!(@photos_schema)
+ with :ok <- Typesense.delete_collection!(@photos_schema["name"]),
+ :ok <- create_collection!() do
+ :ok
+ end
end 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end |
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.
Security: Improve credentials handling in the shell script example.
The current example shows sensitive credentials in plain text, which could lead to security issues if committed to version control.
Consider these improvements:
.env
file approach:.env.example
file template:Add instructions for obtaining the required credentials:
Update the .gitignore to exclude the .env file: