feat: link uuid + increase counter concurrently
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
-- +micrate Up
|
||||
-- SQL in section 'Up' is executed when this migration is applied
|
||||
CREATE TABLE links (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
slug VARCHAR(100) UNIQUE NOT NULL,
|
||||
url TEXT NOT NULL,
|
||||
click_counter INTEGER DEFAULT 0,
|
||||
click_counter INTEGER NOT NULL DEFAULT 0,
|
||||
created_at INTEGER DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
updated_at INTEGER DEFAULT CURRENT_TIMESTAMP NOT NULL
|
||||
);
|
||||
|
||||
+27
-2
@@ -1,3 +1,5 @@
|
||||
require "uuid"
|
||||
|
||||
require "../lib/controller.cr"
|
||||
|
||||
module App::Controllers::Link
|
||||
@@ -11,6 +13,7 @@ module App::Controllers::Link
|
||||
raise App::BadRequestException.new(env) if !url #TODO: return url "required field" error message
|
||||
|
||||
link = Link.new
|
||||
link.id = UUID.v4().to_s
|
||||
link.url = url.to_s
|
||||
link.slug = Random::Secure.urlsafe_base64(4)
|
||||
|
||||
@@ -36,11 +39,33 @@ module App::Controllers::Link
|
||||
link = Database.get_by(Link, slug: slug)
|
||||
raise App::NotFoundException.new(env) if !link
|
||||
|
||||
#TODO: update click_counter
|
||||
spawn do
|
||||
link.click_counter = link.click_counter! + 1
|
||||
|
||||
changeset = Database.update(link)
|
||||
if changeset.errors.any?
|
||||
Log.error { "Increase click counter failed: #{changeset.errors}"}
|
||||
end
|
||||
end
|
||||
|
||||
env.redirect link.url!
|
||||
end
|
||||
end
|
||||
|
||||
#TODO: update, delete, list links
|
||||
class Get < App::Lib::BaseController
|
||||
include App::Models
|
||||
include App::Lib
|
||||
|
||||
def call(env)
|
||||
id = env.params.url["id"]
|
||||
|
||||
link = Database.get(Link, id)
|
||||
raise App::NotFoundException.new(env) if !link
|
||||
|
||||
response = {"data" => App::Serializers::Link.new(link) }
|
||||
response.to_json
|
||||
end
|
||||
end
|
||||
|
||||
#TODO: update, delete
|
||||
end
|
||||
|
||||
+2
-1
@@ -4,9 +4,10 @@ require "crecto"
|
||||
module App::Models
|
||||
class Link < Crecto::Model
|
||||
schema :links do
|
||||
field :id, String, primary_key: true
|
||||
field :slug, String
|
||||
field :url, String
|
||||
field :click_counter, Int64
|
||||
field :click_counter, Int64, default: 0
|
||||
end
|
||||
|
||||
validate_required [:slug, :url]
|
||||
|
||||
@@ -13,6 +13,10 @@ module App
|
||||
Controllers::Link::Index.new.call(env)
|
||||
end
|
||||
|
||||
get "/api/links/:id" do |env|
|
||||
Controllers::Link::Get.new.call(env)
|
||||
end
|
||||
|
||||
post "/api/links" do |env|
|
||||
Controllers::Link::Create.new.call(env)
|
||||
end
|
||||
|
||||
@@ -9,8 +9,10 @@ module App::Serializers
|
||||
|
||||
def to_json(builder : JSON::Builder)
|
||||
builder.object do
|
||||
builder.field("origin", @link.url)
|
||||
builder.field("id", @link.id)
|
||||
builder.field("link", "#{ENV["APP_URL"]}/#{@link.slug}")
|
||||
builder.field("clicks", @link.click_counter)
|
||||
builder.field("origin", @link.url)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user