proto: added subreddits proto
This commit is contained in:
parent
3ae3606ca1
commit
114a6d5116
|
@ -5,8 +5,8 @@ CREATE TABLE subreddits (
|
||||||
disable_scheduler TINYINT NOT NULL DEFAULT 0,
|
disable_scheduler TINYINT NOT NULL DEFAULT 0,
|
||||||
"type" VARCHAR(5) NOT NULL DEFAULT 'r',
|
"type" VARCHAR(5) NOT NULL DEFAULT 'r',
|
||||||
schedule VARCHAR(20) NOT NULL DEFAULT '@daily',
|
schedule VARCHAR(20) NOT NULL DEFAULT '@daily',
|
||||||
countback INT NOT NULL DEFAULT 300,
|
countback BIGINT NOT NULL DEFAULT 300,
|
||||||
image_cover VARCHAR(255) NOT NULL DEFAULT '',
|
cover_image_id INTEGER,
|
||||||
created_at BIGINT DEFAULT (strftime('%s', 'now')) NOT NULL,
|
created_at BIGINT DEFAULT (strftime('%s', 'now')) NOT NULL,
|
||||||
updated_at BIGINT DEFAULT (strftime('%s', 'now')) NOT NULL
|
updated_at BIGINT DEFAULT (strftime('%s', 'now')) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
|
@ -27,7 +27,10 @@ CREATE TABLE images(
|
||||||
CONSTRAINT fk_image_devices_slug
|
CONSTRAINT fk_image_devices_slug
|
||||||
FOREIGN KEY (device)
|
FOREIGN KEY (device)
|
||||||
REFERENCES devices(slug)
|
REFERENCES devices(slug)
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_image_subreddit_cover
|
||||||
|
FOREIGN KEY (id)
|
||||||
|
REFERENCES subreddits(cover_image_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX idx_subreddit_images_blacklisted ON images(subreddit, blacklisted);
|
CREATE INDEX idx_subreddit_images_blacklisted ON images(subreddit, blacklisted);
|
||||||
|
@ -36,6 +39,21 @@ CREATE INDEX idx_images_nsfw_blacklisted ON images(nsfw, blacklisted);
|
||||||
CREATE INDEX idx_images_created_at_nsfw_blacklisted ON images(created_at DESC, nsfw, blacklisted);
|
CREATE INDEX idx_images_created_at_nsfw_blacklisted ON images(created_at DESC, nsfw, blacklisted);
|
||||||
CREATE INDEX idx_images_blacklisted ON images(blacklisted);
|
CREATE INDEX idx_images_blacklisted ON images(blacklisted);
|
||||||
CREATE UNIQUE INDEX idx_unique_images_per_device ON images(device, post_name);
|
CREATE UNIQUE INDEX idx_unique_images_per_device ON images(device, post_name);
|
||||||
|
|
||||||
|
CREATE TRIGGER images_update_timestamp AFTER UPDATE ON images FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE images SET updated_at = strftime('%s', 'now') WHERE id = old.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER images_update_subreddit_cover_on_insert AFTER INSERT ON images FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE subreddits SET cover_image_id = new.id WHERE name = new.subreddit AND cover_image_id IS NULL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER images_update_subreddit_cover_on_delete AFTER DELETE ON images FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE subreddits SET cover_image_id = NULL WHERE cover_image_id = old.id;
|
||||||
|
END;
|
||||||
-- +goose StatementEnd
|
-- +goose StatementEnd
|
||||||
|
|
||||||
-- +goose Down
|
-- +goose Down
|
||||||
|
|
32
schemas/proto/subreddits/v1/create.proto
Normal file
32
schemas/proto/subreddits/v1/create.proto
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package subreddits.v1;
|
||||||
|
|
||||||
|
import "buf/validate/validate.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tigorlazuardi/bluemage/go/gen/proto/subreddits/v1";
|
||||||
|
|
||||||
|
message CreateSubredditRequest {
|
||||||
|
// name of the subreddits to insert.
|
||||||
|
//
|
||||||
|
// accept insensitive casing, but casing
|
||||||
|
// will change to what Reddit has for
|
||||||
|
// consistency.
|
||||||
|
string name = 1 [(buf.validate.field).string.min_len = 1];
|
||||||
|
bool disable_scheduler = 2;
|
||||||
|
SubredditType type = 3;
|
||||||
|
// schedule is cron job spec to set schedule on when
|
||||||
|
// the runner for this subreddit runs.
|
||||||
|
string schedule = 4 [(buf.validate.field).string.min_len = 1];
|
||||||
|
uint32 countback = 5 [(buf.validate.field).uint32.gt = 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SubredditType {
|
||||||
|
SUBREDDIT_TYPE_UNSPECIFIED = 0;
|
||||||
|
SUBREDDIT_TYPE_SUBREDDIT = 1;
|
||||||
|
SUBREDDIT_TYPE_USER = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateSubredditResponse {
|
||||||
|
string name = 1;
|
||||||
|
}
|
25
schemas/proto/subreddits/v1/delete.proto
Normal file
25
schemas/proto/subreddits/v1/delete.proto
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package subreddits.v1;
|
||||||
|
|
||||||
|
import "buf/validate/validate.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tigorlazuardi/bluemage/go/gen/proto/subreddits/v1";
|
||||||
|
|
||||||
|
message DeleteSubredditRequest {
|
||||||
|
// name of the subreddit to delete
|
||||||
|
string name = 1 [(buf.validate.field).string.min_len = 1];
|
||||||
|
|
||||||
|
// if true, delete all images associated with the subreddit
|
||||||
|
// from disk as well.
|
||||||
|
bool delete_images = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeleteSubredditResponse {
|
||||||
|
// name of the subreddit that was deleted.
|
||||||
|
string name = 1;
|
||||||
|
// number of images that were deleted.
|
||||||
|
//
|
||||||
|
// always 0 if delete_images is false.
|
||||||
|
uint32 deleted_images = 2;
|
||||||
|
}
|
42
schemas/proto/subreddits/v1/get.proto
Normal file
42
schemas/proto/subreddits/v1/get.proto
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package subreddits.v1;
|
||||||
|
|
||||||
|
import "buf/validate/validate.proto";
|
||||||
|
import "subreddits/v1/create.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tigorlazuardi/bluemage/go/gen/proto/subreddits/v1";
|
||||||
|
|
||||||
|
message GetSubredditRequest {
|
||||||
|
// name of the subreddit. Case insensitive.
|
||||||
|
//
|
||||||
|
// Returns error on not found.
|
||||||
|
string name = 1 [(buf.validate.field).string.min_len = 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetSubredditResponse {
|
||||||
|
string name = 1;
|
||||||
|
bool disable_scheduler = 2;
|
||||||
|
// type is never unspecified for this response.
|
||||||
|
//
|
||||||
|
// It's always either `SUBREDDIT_TYPE_SUBREDDIT`
|
||||||
|
// or `SUBREDDIT_TYPE_USER`.
|
||||||
|
SubredditType type = 3;
|
||||||
|
string schedule = 4;
|
||||||
|
uint32 countback = 5;
|
||||||
|
// cover_image_id is the id of an image that
|
||||||
|
// acts as the cover for this subreddit.
|
||||||
|
//
|
||||||
|
// May not be present in these kind of situations:
|
||||||
|
//
|
||||||
|
// - The background task runner has not run for this subreddit.
|
||||||
|
// - The image that is used as cover is deleted.
|
||||||
|
// - The subreddit does not contain any images.
|
||||||
|
//
|
||||||
|
// cover_image_id changes after every insert of
|
||||||
|
// new images in that subreddit, so avoid
|
||||||
|
// caching the image for too long.
|
||||||
|
optional uint32 cover_image_id = 6;
|
||||||
|
int64 created_at = 7;
|
||||||
|
int64 updated_at = 8;
|
||||||
|
}
|
19
schemas/proto/subreddits/v1/list.proto
Normal file
19
schemas/proto/subreddits/v1/list.proto
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package subreddits.v1;
|
||||||
|
|
||||||
|
import "buf/validate/validate.proto";
|
||||||
|
import "subreddits/v1/get.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tigorlazuardi/bluemage/go/gen/proto/subreddits/v1";
|
||||||
|
|
||||||
|
message ListSubredditsRequest {
|
||||||
|
// name of the subreddit. Case insensitive.
|
||||||
|
//
|
||||||
|
// Returns error on not found.
|
||||||
|
string name = 1 [(buf.validate.field).string.min_len = 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListSubredditsResponse {
|
||||||
|
repeated GetSubredditResponse images = 1;
|
||||||
|
}
|
17
schemas/proto/subreddits/v1/resolve.proto
Normal file
17
schemas/proto/subreddits/v1/resolve.proto
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package subreddits.v1;
|
||||||
|
|
||||||
|
import "buf/validate/validate.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tigorlazuardi/bluemage/go/gen/proto/subreddits/v1";
|
||||||
|
|
||||||
|
message ResolveSubredditNameRequest {
|
||||||
|
// name of the subreddit to resolve (check existence and casing).
|
||||||
|
string name = 1 [(buf.validate.field).string.min_len = 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResolveSubredditNameResponse {
|
||||||
|
// resolved the actual subreddit name.
|
||||||
|
string resolved = 1;
|
||||||
|
}
|
53
schemas/proto/subreddits/v1/subreddits.proto
Normal file
53
schemas/proto/subreddits/v1/subreddits.proto
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package subreddits.v1;
|
||||||
|
|
||||||
|
import "subreddits/v1/create.proto";
|
||||||
|
import "subreddits/v1/delete.proto";
|
||||||
|
import "subreddits/v1/get.proto";
|
||||||
|
import "subreddits/v1/list.proto";
|
||||||
|
import "subreddits/v1/resolve.proto";
|
||||||
|
import "subreddits/v1/update.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tigorlazuardi/bluemage/go/gen/proto/subreddits/v1";
|
||||||
|
|
||||||
|
service SubredditsService {
|
||||||
|
// CreateSubreddit creates a new subreddit
|
||||||
|
//
|
||||||
|
// Returns the subreddit name.
|
||||||
|
//
|
||||||
|
// Returns the following error codes:
|
||||||
|
// - connect.CodeAlreadyExists if subreddit with the same name already exists.
|
||||||
|
// - connect.CodeInvalidArgument if validation failed, e.g. Invalid schedule cron format.
|
||||||
|
// - connect.CodeNotFound if the subreddit does not exist.
|
||||||
|
rpc CreateSubreddit(CreateSubredditRequest) returns (CreateSubredditResponse);
|
||||||
|
|
||||||
|
// GetSubreddit returns a subreddit by its name.
|
||||||
|
//
|
||||||
|
// Returns error with connect.CodeNotFound if subreddit does not exist.
|
||||||
|
rpc GetSubreddit(GetSubredditRequest) returns (GetSubredditResponse);
|
||||||
|
|
||||||
|
// ListSubreddits returns a list of subreddits.
|
||||||
|
rpc ListSubreddits(ListSubredditsRequest) returns (ListSubredditsResponse);
|
||||||
|
|
||||||
|
// UpdateSubreddit updates a subreddit.
|
||||||
|
//
|
||||||
|
// Only the fields that are set in the request will be updated.
|
||||||
|
//
|
||||||
|
// Returns error with connect.CodeNotFound if subreddit does not exist.
|
||||||
|
rpc UpdateSubreddit(UpdateSubredditRequest) returns (UpdateSubredditResponse);
|
||||||
|
|
||||||
|
// DeleteSubreddit deletes a subreddit.
|
||||||
|
//
|
||||||
|
// Returns error with connect.CodeNotFound if subreddit does not exist.
|
||||||
|
rpc DeleteSubreddit(DeleteSubredditRequest) returns (DeleteSubredditResponse);
|
||||||
|
|
||||||
|
// ResolveSubredditName resolves the given subreddit name.
|
||||||
|
//
|
||||||
|
// The returned resolved_name is the name that is actually
|
||||||
|
// used in Reddit.
|
||||||
|
//
|
||||||
|
// Returns error with connect.CodeNotFound if subreddit does not exist.
|
||||||
|
// So this rpc endpoint also acts to check subreddit's existence.
|
||||||
|
rpc ResolveSubredditName(ResolveSubredditNameRequest) returns (ResolveSubredditNameResponse);
|
||||||
|
}
|
24
schemas/proto/subreddits/v1/update.proto
Normal file
24
schemas/proto/subreddits/v1/update.proto
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package subreddits.v1;
|
||||||
|
|
||||||
|
import "buf/validate/validate.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/tigorlazuardi/bluemage/go/gen/proto/subreddits/v1";
|
||||||
|
|
||||||
|
message UpdateSubredditRequest {
|
||||||
|
// The name of the subreddit to update.
|
||||||
|
string name = 1 [(buf.validate.field).string.min_len = 1];
|
||||||
|
SubredditSetter set = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SubredditSetter {
|
||||||
|
optional bool disable_scheduler = 1;
|
||||||
|
optional string schedule = 2 [(buf.validate.field).string.min_len = 1];
|
||||||
|
optional int64 countback = 3 [(buf.validate.field).int64.gt = 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateSubredditResponse {
|
||||||
|
// The updated subreddit.
|
||||||
|
string name = 1;
|
||||||
|
}
|
Loading…
Reference in a new issue