landed fixseen and got rid of all explicit LOCK TABLES operations (not needed in modern MySQL, especially with transaction semantics)
This commit is contained in:
@@ -184,6 +184,24 @@ func SetPseud(ctxt ui.AmContext) (string, any, error) {
|
|||||||
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias")), nil
|
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias")), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ConfFixseen marks all messages in a conference as read.
|
||||||
|
* Parameters:
|
||||||
|
* ctxt - The AmContext for the request.
|
||||||
|
* Returns:
|
||||||
|
* Command string dictating what to be rendered.
|
||||||
|
* Data as a parameter for the command string.
|
||||||
|
* Standard Go error status.
|
||||||
|
*/
|
||||||
|
func ConfFixseen(ctxt ui.AmContext) (string, any, error) {
|
||||||
|
comm := ctxt.CurrentCommunity()
|
||||||
|
conf := ctxt.GetScratch("currentConference").(*database.Conference)
|
||||||
|
err := conf.Fixseen(ctxt.Ctx(), ctxt.CurrentUser())
|
||||||
|
if err != nil {
|
||||||
|
return ui.ErrorPage(ctxt, err)
|
||||||
|
}
|
||||||
|
return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias")), nil
|
||||||
|
}
|
||||||
|
|
||||||
/* AddToHotlist adds the current community and conference to the user's hotlist..
|
/* AddToHotlist adds the current community and conference to the user's hotlist..
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* ctxt - The AmContext for the request.
|
* ctxt - The AmContext for the request.
|
||||||
|
|||||||
@@ -347,6 +347,71 @@ func (c *Conference) UnreadMessages(ctx context.Context, u *User) (int32, error)
|
|||||||
return rc, err
|
return rc, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fixseenData is a temporary structure used in assisting with Fixseen.
|
||||||
|
type fixseenData struct {
|
||||||
|
topicid int32
|
||||||
|
topmessage int32
|
||||||
|
insert bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fixseen marks all messages in a conference as read.
|
||||||
|
func (c *Conference) Fixseen(ctx context.Context, u *User) error {
|
||||||
|
if u.IsAnon {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
success := false
|
||||||
|
tx := amdb.MustBegin()
|
||||||
|
defer func() {
|
||||||
|
if !success {
|
||||||
|
tx.Rollback()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Get a count of topics beforehand.
|
||||||
|
row := tx.QueryRowContext(ctx, "SELECT COUNT(*) FROM topics WHERE confid = ?", c.ConfId)
|
||||||
|
count := 0
|
||||||
|
err := row.Scan(&count)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the list of all topics.
|
||||||
|
rs, err := tx.QueryContext(ctx, `SELECT t.topicid, t.top_message, ISNULL(s.last_message) FROM topics t
|
||||||
|
LEFT JOIN topicsettings s ON t.topicid = s.topicid AND s.uid = ? WHERE t.confid = ?`, u.Uid, c.ConfId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
work := make([]fixseenData, 0, count)
|
||||||
|
for rs.Next() {
|
||||||
|
var d fixseenData
|
||||||
|
err = rs.Scan(&(d.topicid), &(d.topmessage), &(d.insert))
|
||||||
|
work = append(work, d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust each topic in turn.
|
||||||
|
for _, d := range work {
|
||||||
|
if d.insert {
|
||||||
|
_, err = tx.ExecContext(ctx, "INSERT INTO topicsettings (topicid, uid, last_message, last_read) VALUES (?, ?, ?, NOW())", d.topicid, u.Uid, d.topmessage)
|
||||||
|
} else {
|
||||||
|
_, err = tx.ExecContext(ctx, "UPDATE topicsettings SET last_message = ?, last_read = NOW() WHERE topicid = ? AND uid = ?", d.topmessage, d.topicid, u.Uid)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also update last-read in conference.
|
||||||
|
if _, err = c.TouchRead(ctx, tx, u); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = tx.Commit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
success = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
/* AmGetConference returns a conference given its ID.
|
/* AmGetConference returns a conference given its ID.
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* ctx - Standard Go context value.
|
* ctx - Standard Go context value.
|
||||||
|
|||||||
@@ -284,14 +284,6 @@ func (p *PostHeader) Scribble(ctx context.Context, u *User, ipaddr string) error
|
|||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
unlock := true
|
|
||||||
tx.ExecContext(ctx, "LOCK TABLES posts WRITE, postdata WRITE, postattach WRITE, postpublish WRITE;")
|
|
||||||
defer func() {
|
|
||||||
if unlock {
|
|
||||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Scribble on the post header.
|
// Scribble on the post header.
|
||||||
scribblePseud := "<EM><B>(Scribbled)</B></EM>" // FUTURE: configurable option
|
scribblePseud := "<EM><B>(Scribbled)</B></EM>" // FUTURE: configurable option
|
||||||
_, err := tx.ExecContext(ctx, "UPDATE posts SET linecount = 0, hidden = 0, scribble_uid = ?, scribble_date = NOW(), pseud = ? WHERE postid = ?", u.Uid, scribblePseud, p.PostId)
|
_, err := tx.ExecContext(ctx, "UPDATE posts SET linecount = 0, hidden = 0, scribble_uid = ?, scribble_date = NOW(), pseud = ? WHERE postid = ?", u.Uid, scribblePseud, p.PostId)
|
||||||
@@ -318,9 +310,6 @@ func (p *PostHeader) Scribble(ctx context.Context, u *User, ipaddr string) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock tables and commit.
|
|
||||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
|
||||||
unlock = false
|
|
||||||
if err = tx.Commit(); err != nil {
|
if err = tx.Commit(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -353,13 +342,6 @@ func (p *PostHeader) Nuke(ctx context.Context, u *User, ipaddr string) error {
|
|||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
unlock := true
|
|
||||||
tx.ExecContext(ctx, "LOCK TABLES posts WRITE, postdata WRITE, postattach WRITE, postdogear WRITE, postpublish WRITE, topics WRITE, topicsettings WRITE;")
|
|
||||||
defer func() {
|
|
||||||
if unlock {
|
|
||||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Delete all the references to this post.
|
// Delete all the references to this post.
|
||||||
_, err := tx.ExecContext(ctx, "DELETE FROM posts WHERE postid = ?", p.PostId)
|
_, err := tx.ExecContext(ctx, "DELETE FROM posts WHERE postid = ?", p.PostId)
|
||||||
@@ -399,9 +381,6 @@ func (p *PostHeader) Nuke(ctx context.Context, u *User, ipaddr string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock tables and commit.
|
|
||||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
|
||||||
unlock = false
|
|
||||||
if err = tx.Commit(); err != nil {
|
if err = tx.Commit(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -486,13 +465,6 @@ func (p *PostHeader) MoveTo(ctx context.Context, target *Topic, u *User, ipaddr
|
|||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
unlock := true
|
|
||||||
tx.ExecContext(ctx, "LOCK TABLES confs WRITE, topics WRITE, posts WRITE, topicsettings WRITE;")
|
|
||||||
defer func() {
|
|
||||||
if unlock {
|
|
||||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Adjust post record in the database to make it part of the new topic.
|
// Adjust post record in the database to make it part of the new topic.
|
||||||
_, err = tx.ExecContext(ctx, "UPDATE posts SET parent = 0, topicid = ?, num = ? WHERE postid = ?", target.TopicId, target.TopMessage+1, p.PostId)
|
_, err = tx.ExecContext(ctx, "UPDATE posts SET parent = 0, topicid = ?, num = ? WHERE postid = ?", target.TopicId, target.TopMessage+1, p.PostId)
|
||||||
@@ -534,9 +506,6 @@ func (p *PostHeader) MoveTo(ctx context.Context, target *Topic, u *User, ipaddr
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock tables and commit.
|
|
||||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
|
||||||
unlock = false
|
|
||||||
if err = tx.Commit(); err != nil {
|
if err = tx.Commit(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -625,13 +594,6 @@ func AmNewPost(ctx context.Context, conf *Conference, topic *Topic, user *User,
|
|||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
unlock := true
|
|
||||||
tx.ExecContext(ctx, "LOCK TABLES confs WRITE, topics WRITE, topicsettings WRITE, posts WRITE, postdata WRITE;")
|
|
||||||
defer func() {
|
|
||||||
if unlock {
|
|
||||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Add the post header information.
|
// Add the post header information.
|
||||||
rs, err := tx.ExecContext(ctx, "INSERT INTO posts (topicid, num, linecount, creator_uid, posted, pseud) VALUES (?, ?, ?, ?, NOW(), ?)",
|
rs, err := tx.ExecContext(ctx, "INSERT INTO posts (topicid, num, linecount, creator_uid, posted, pseud) VALUES (?, ?, ?, ?, NOW(), ?)",
|
||||||
@@ -671,9 +633,6 @@ func AmNewPost(ctx context.Context, conf *Conference, topic *Topic, user *User,
|
|||||||
topic.TopMessage = hdr.Num
|
topic.TopMessage = hdr.Num
|
||||||
topic.LastUpdate = hdr.Posted
|
topic.LastUpdate = hdr.Posted
|
||||||
|
|
||||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
|
||||||
unlock = false
|
|
||||||
|
|
||||||
// update the "last update" date of the conference and the "last posted" date in the conference settings
|
// update the "last update" date of the conference and the "last posted" date in the conference settings
|
||||||
if err = conf.TouchUpdate(ctx, tx, hdr.Posted); err != nil {
|
if err = conf.TouchUpdate(ctx, tx, hdr.Posted); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
+1
-23
@@ -349,14 +349,6 @@ func (t *Topic) Delete(ctx context.Context, u *User, ipaddr string, background *
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
unlock := true
|
|
||||||
tx.ExecContext(ctx, "LOCK TABLES confs WRITE, topics WRITE, topicsettings WRITE, topicbozo WRITE;")
|
|
||||||
defer func() {
|
|
||||||
if unlock {
|
|
||||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
conf, err := AmGetConference(ctx, t.ConfId)
|
conf, err := AmGetConference(ctx, t.ConfId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -373,12 +365,9 @@ func (t *Topic) Delete(ctx context.Context, u *User, ipaddr string, background *
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = conf.TouchUpdate(ctx, tx, time.Now())
|
if err = conf.TouchUpdate(ctx, tx, time.Now()); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
|
||||||
unlock = false
|
|
||||||
if err = tx.Commit(); err != nil {
|
if err = tx.Commit(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -670,14 +659,6 @@ func AmNewTopic(ctx context.Context, conf *Conference, user *User, title string,
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
unlock := true
|
|
||||||
tx.ExecContext(ctx, "LOCK TABLES confs WRITE, topics WRITE, topicsettings WRITE, posts WRITE, postdata WRITE;")
|
|
||||||
defer func() {
|
|
||||||
if unlock {
|
|
||||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Insert the new topic into the database.
|
// Insert the new topic into the database.
|
||||||
conf.Mutex.Lock()
|
conf.Mutex.Lock()
|
||||||
rs, err := tx.ExecContext(ctx, "INSERT INTO topics (confid, num, creator_uid, createdate, lastupdate, name) VALUES (?, ?, ?, NOW(), NOW(), ?)",
|
rs, err := tx.ExecContext(ctx, "INSERT INTO topics (confid, num, creator_uid, createdate, lastupdate, name) VALUES (?, ?, ?, NOW(), NOW(), ?)",
|
||||||
@@ -732,9 +713,6 @@ func AmNewTopic(ctx context.Context, conf *Conference, user *User, title string,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
|
||||||
unlock = false
|
|
||||||
|
|
||||||
// update the "last posted" date in the conference settings
|
// update the "last posted" date in the conference settings
|
||||||
_, err = conf.TouchPost(ctx, tx, user, topic.CreateDate)
|
_, err = conf.TouchPost(ctx, tx, user, topic.CreateDate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -694,13 +694,6 @@ func AmCreateNewUser(ctx context.Context, username string, password string, remi
|
|||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
unlock := true
|
|
||||||
tx.ExecContext(ctx, "LOCK TABLES users WRITE, userprefs WRITE, propuser WRITE, commmember WRITE, sideboxes WRITE, confhotlist WRITE;")
|
|
||||||
defer func() {
|
|
||||||
if unlock {
|
|
||||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Test if the user name is already taken.
|
// Test if the user name is already taken.
|
||||||
row := tx.QueryRowContext(ctx, "SELECT uid FROM users WHERE username = ?", username)
|
row := tx.QueryRowContext(ctx, "SELECT uid FROM users WHERE username = ?", username)
|
||||||
@@ -749,9 +742,6 @@ func AmCreateNewUser(ctx context.Context, username string, password string, remi
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.ExecContext(ctx, "UNLOCK TABLES;")
|
|
||||||
unlock = false
|
|
||||||
|
|
||||||
if err = tx.Commit(); err != nil {
|
if err = tx.Commit(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ _(italicized items can be deferred)_
|
|||||||
- Find
|
- Find
|
||||||
- Manage:
|
- Manage:
|
||||||
- ~~Set pseud~~
|
- ~~Set pseud~~
|
||||||
- Fixseen
|
- ~~Fixseen~~
|
||||||
- ~~Send invite~~
|
- ~~Send invite~~
|
||||||
- Change information
|
- Change information
|
||||||
- Manage aliases
|
- Manage aliases
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ func setupEcho() *echo.Echo {
|
|||||||
confGroup.POST("/new_topic", ui.AmWrap(NewTopic))
|
confGroup.POST("/new_topic", ui.AmWrap(NewTopic))
|
||||||
confGroup.GET("/manage", ui.AmWrap(ConfManage))
|
confGroup.GET("/manage", ui.AmWrap(ConfManage))
|
||||||
confGroup.POST("/pseud", ui.AmWrap(SetPseud))
|
confGroup.POST("/pseud", ui.AmWrap(SetPseud))
|
||||||
|
confGroup.GET("/fixseen", ui.AmWrap(ConfFixseen))
|
||||||
confGroup.GET("/hotlist", ui.AmWrap(AddToHotlist))
|
confGroup.GET("/hotlist", ui.AmWrap(AddToHotlist))
|
||||||
confGroup.GET("/invite", ui.AmWrap(InviteToConference))
|
confGroup.GET("/invite", ui.AmWrap(InviteToConference))
|
||||||
confGroup.GET("/r/:topic", ui.AmWrap(ReadPosts), ui.SetTopic)
|
confGroup.GET("/r/:topic", ui.AmWrap(ReadPosts), ui.SetTopic)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
<!-- Fixseen link -->
|
<!-- Fixseen link -->
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<a class="text-blue-700 hover:text-blue-900 text-sm font-bold" href="/TODO/{{ urlStem }}/fixseen">Mark entire conference as read (fixseen)</a>
|
<a class="text-blue-700 hover:text-blue-900 text-sm font-bold" href="{{ urlStem }}/fixseen">Mark entire conference as read (fixseen)</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{ if canInvite }}
|
{{ if canInvite }}
|
||||||
|
|||||||
Reference in New Issue
Block a user