Skip to content

Commit

Permalink
Change each service to act like a transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
seunghyukcho committed Jul 17, 2019
1 parent 9aa2b82 commit 3a630db
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 70 deletions.
9 changes: 9 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,21 @@ func main() {

port, name, address, id, password := os.Getenv("PORT"), os.Getenv("DB_NAME"), os.Getenv("DB_HOST"), os.Getenv("DB_ID"), os.Getenv("DB_PW")
rssDB := rsserver.DB{}

if err := rssDB.Open(name, address, id, password); err != nil {
panic(err)
}

defer rssDB.Close()

if err := rssDB.Create(); err != nil {
panic(err)
}

if err := rssDB.Update(); err != nil {
panic(err)
}

go func(db *rsserver.DB) {
ticker := time.NewTicker(1 * time.Hour)

Expand Down
2 changes: 1 addition & 1 deletion rssapi/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (server *Server) CreateChannel(ctx *gin.Context) {
if err := server.DB.ChannelTable.Create(rss.Link); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
} else {
ctx.JSON(http.StatusBadRequest, gin.H{"success": "successfully created a new Channel"})
ctx.JSON(http.StatusOK, gin.H{"success": "successfully created a new Channel"})
}
} else {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Request body doesn't match the api... Please read our api docs"})
Expand Down
11 changes: 11 additions & 0 deletions rsserver/handle/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package handle

import "database/sql"

func Transaction(tx *sql.Tx, e error) (err error) {
if err := tx.Rollback(); err != nil {
return err
}

return e
}
42 changes: 20 additions & 22 deletions rsserver/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,41 +14,39 @@ type DB struct {
}

const (
itemSchema = `CREATE TABLE Item (
itemSchema = `CREATE TABLE IF NOT EXISTS Item (
item_id INT NOT NULL AUTO_INCREMENT,
guid VARCHAR(30) NOT NULL,
guid VARCHAR(30) NOT NULL UNIQUE,
title VARCHAR(255),
link VARCHAR(255),
description TEXT,
pub_date DATETIME,
creator VARCHAR(255),
CONSTRAINT PRIMARY KEY (item_id),
CONSTRAINT INDEX (item_id),
CONSTRAINT UNIQUE (guid)`
INDEX (item_id),
PRIMARY KEY (item_id))`

enclosureSchema = `CREATE TABLE Enclosure (
enclosureSchema = `CREATE TABLE IF NOT EXISTS Enclosure (
item INT NOT NULL,
url VARCHAR(255) NOT NULL,
url VARCHAR(255) NOT NULL UNIQUE,
length VARCHAR(30),
type VARCHAR(30),
CONSTRAINT PRIMARY KEY (item, url),
CONSTRAINT INDEX (item),
CONSTRAINT FOREIGN KEY (item) REFERENCES Item(item_id)`
INDEX (item),
PRIMARY KEY (item, url),
FOREIGN KEY (item) REFERENCES Item(item_id))`

channelSchema = `CREATE TABLE Channel (
channelSchema = `CREATE TABLE IF NOT EXISTS Channel (
channel_id INT NOT NULL AUTO_INCREMENT,
title VARCHAR(255),
description VARCHAR(255),
site_link VARCHAR(255),
rss_link VARCHAR(255) NOT NULL,
CONSTRAINT PRIMARY KEY (channel_id)
CONSTRAINT UNIQUE (rss_link)`
title VARCHAR(255) DEFAULT "",
description VARCHAR(255) DEFAULT "",
site_link VARCHAR(255) DEFAULT "",
rss_link VARCHAR(255) NOT NULL UNIQUE,
INDEX (channel_id),
PRIMARY KEY (channel_id))`

publishSchema = `CREATE TABLE Publish (
publishSchema = `CREATE TABLE IF NOT EXISTS Publish (
item INT NOT NULL,
channel INT NOT NULL,
CONSTRAINT PRIMARY KEY (item, channel),
CONSTRAINT INDEX (channel),
CONSTRAINT FOREIGN KEY (item) REFERENCES Item(item_id),
CONSTRAINT FOREIGN KEY (channel) REFERENCES Channel(channel_id)`
PRIMARY KEY (item, channel),
FOREIGN KEY (item) REFERENCES Item(item_id),
FOREIGN KEY (channel) REFERENCES Channel(channel_id))`
)
72 changes: 49 additions & 23 deletions rsserver/rsschannel/controller.go
Original file line number Diff line number Diff line change
@@ -1,90 +1,116 @@
package rsschannel

import (
"database/sql"
"github.com/mmcdole/gofeed"
"github.com/shhj1998/rss-search-api/rsserver/handle"
"github.com/shhj1998/rss-search-api/rsserver/rssitem"
)

func (table *Table) GetLinks(channels *[]*Schema) (err error) {
channelRows, err := table.Connection.Query(`SELECT channel_id, rss_link FROM Channel`)
var tx *sql.Tx
if tx, err = table.Connection.Begin(); err != nil {
return err
}

channelRows, err := tx.Query(`SELECT channel_id, rss_link FROM Channel`)

if err == nil {
for channelRows.Next() {
var link Schema
if err := channelRows.Scan(&link.Id, &link.RSSLink); err != nil {
return nil
return handle.Transaction(tx, err)
}

*channels = append(*channels, &link)
}
} else {
return err
return handle.Transaction(tx, err)
}

return nil
return tx.Commit()
}

func (table *Table) Get(channels *[]*Schema) (err error) {
channelRows, err := table.Connection.Query(`SELECT title, description, site_link FROM Channel`)
var tx *sql.Tx
if tx, err = table.Connection.Begin(); err != nil {
return err
}

channelRows, err := tx.Query(`SELECT channel_id, title, description, site_link, rss_link FROM Channel`)

if err == nil {
if err := Fetch(channelRows, channels); err != nil {
return err
return handle.Transaction(tx, err)
}
} else {
return err
return handle.Transaction(tx, err)
}

return nil
return tx.Commit()
}

func (table *Table) getChannelWithItems(channel *Schema, count int) (err error) {
var tx *sql.Tx
var items []*rssitem.Schema
itemRows, err := table.Connection.Query(`SELECT I.guid, I.title, I.link, I.description, I.pub_date, I.creator, e.url, e.length, e.type
FROM Channel c JOIN Publish p ON c.channel_id=p.channel JOIN Item I ON p.item=I.guid LEFT JOIN Enclosure e ON I.guid=e.item

if tx, err = table.Connection.Begin(); err != nil {
return err
}

itemRows, err := tx.Query(`SELECT I.guid, I.title, I.link, I.description, I.pub_date, I.creator, e.url, e.length, e.type
FROM Channel c JOIN Publish p ON c.channel_id=p.channel JOIN Item I ON p.item=I.item_id LEFT JOIN Enclosure e ON I.guid=e.item
WHERE channel_id=? ORDER BY I.pub_date DESC LIMIT 0,?`, channel.Id, count)
if err != nil {
return err
return handle.Transaction(tx, err)
} else if err = rssitem.Fetch(itemRows, &items); err != nil {
return err
return handle.Transaction(tx, err)
} else {
for idx := range items {
channel.Items = append(channel.Items, &items[idx].Item)
}
}

return nil
return tx.Commit()
}

func (table *Table) GetWithItems(channels *[]*Schema, count int) (err error) {
channelRows, err := table.Connection.Query(`SELECT channel_id, title, description, site_link, rss_link FROM Channel`)

if err != nil {
var tx *sql.Tx
if tx, err = table.Connection.Begin(); err != nil {
return err
}

if channelRows, err := tx.Query(`SELECT channel_id, title, description, site_link, rss_link FROM Channel`); err != nil {
return handle.Transaction(tx, err)
} else {
if err = Fetch(channelRows, channels); err != nil {
return err
return handle.Transaction(tx, err)
} else {
for idx := range *channels {
if err = table.getChannelWithItems((*channels)[idx], count); err != nil {
return err
return handle.Transaction(tx, err)
}
}
}
}

return nil
return tx.Commit()
}

func (table *Table) Create(rssLink string) (err error) {
var tx *sql.Tx
if tx, err = table.Connection.Begin(); err != nil {
return err
}

fp := gofeed.NewParser()
if _, err = fp.ParseURL(rssLink); err == nil {
if _, err = table.Connection.Exec(`INSERT INTO Channel(rss_link) VALUE(?)`, rssLink); err != nil {
return err
if _, err = tx.Exec(`INSERT INTO Channel(rss_link) VALUE(?)`, rssLink); err != nil {
return handle.Transaction(tx, err)
}
} else {
return err
return handle.Transaction(tx, err)
}

return nil
return tx.Commit()
}
22 changes: 21 additions & 1 deletion rsserver/rsschannel/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,29 @@ import "database/sql"
func Fetch(channels *sql.Rows, ret *[]*Schema) (err error) {
for channels.Next() {
var channel Schema
if err = channels.Scan(&channel.Id, &channel.Title, &channel.Description, &channel.Link, &channel.RSSLink); err != nil {
var title, description, link sql.NullString
if err = channels.Scan(&channel.Id, &title, &description, &link, &channel.RSSLink); err != nil {
return err
}

if title.Valid {
channel.Title = title.String
} else {
channel.Title = " "
}

if description.Valid {
channel.Description = description.String
} else {
channel.Description = " "
}

if link.Valid {
channel.Link = link.String
} else {
channel.Link = " "
}

*ret = append(*ret, &channel)
}
return nil
Expand Down
18 changes: 14 additions & 4 deletions rsserver/rssitem/controller.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
package rssitem

import (
"database/sql"
"github.com/shhj1998/rss-search-api/rsserver/handle"
)

func (table *Table) Get(items *[]*Schema) (err error) {
itemRows, err := table.Connection.Query(`SELECT guid, title, link, description, pub_date, creator, url, length, type FROM Item LEFT JOIN Enclosure ON guid=item`)
var tx *sql.Tx
if tx, err = table.Connection.Begin(); err != nil {
return err
}

itemRows, err := tx.Query(`SELECT guid, title, link, description, pub_date, creator, url, length, type FROM Item LEFT JOIN Enclosure ON item_id=item`)

if err == nil {
if err := Fetch(itemRows, items); err != nil {
return err
return handle.Transaction(tx, err)
}
} else {
return err
return handle.Transaction(tx, err)
}

return nil
return tx.Commit()
}
2 changes: 2 additions & 0 deletions rsserver/rssitem/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ func TestController_GetItems(t *testing.T) {
AddRow("media:news:20190708154212517", "I think it is a good day", "link01", "so do I!", "2019-07-08 06:42:12", nil, nil, nil, nil).
AddRow("media:news:20190708154523636", "It's raining outside...", "link02", "I'm getting tired...", "2019-07-09 07:42:12", nil, nil, nil, nil)

mock.ExpectBegin()
mock.ExpectQuery("SELECT").WillReturnRows(mockRows)
mock.ExpectCommit()
var controller = rssitem.Table{Connection: conn}
err := controller.Get(&actualItems)

Expand Down

0 comments on commit 3a630db

Please sign in to comment.