diff --git a/database/conference.go b/database/conference.go index 9c78824..e947eba 100644 --- a/database/conference.go +++ b/database/conference.go @@ -933,6 +933,81 @@ func (c *Conference) Delete(ctx context.Context, comm *Community, u *User, ipadd return nil } +// The service vtable (see services.go) for the conferencing service. +type conferenceServiceVTable struct{} + +func (*conferenceServiceVTable) OnNewCommunity(context.Context, *sqlx.Tx, *Community) error { + return nil +} + +func (*conferenceServiceVTable) OnDeleteCommunity(ctx context.Context, tx *sqlx.Tx, commid int32, background *util.WorkerPool) error { + // Get the list of conferences in this community. + var confids []int32 + err := tx.SelectContext(ctx, &confids, "SELECT confid FROM commtoconf WHERE commid = ?", commid) + if err != nil { + return err + } + for i, confid := range confids { + // any references to conference other than this community? + row := tx.QueryRowContext(ctx, "SELECT COUNT(*) FROM commtoconf WHERE confid = ? AND commid <> ?", confid, commid) + refCount := 0 + err = row.Scan(&refCount) + if err != nil { + return err + } + // break the link with the community + if _, err = tx.ExecContext(ctx, "DELETE FROM commtoconf WHERE commid = ? AND confid = ?", commid, confid); err != nil { + return err + } + if refCount > 0 { + confids[i] = -1 + continue // done with this conference + } + // We have to delete all the conference core data now. + _, err = tx.ExecContext(ctx, "DELETE FROM confs WHERE confid = ?", confid) + if err == nil { + _, err = tx.ExecContext(ctx, "DELETE FROM confalias WHERE confid = ?", confid) + } + if err != nil { + return err + } + // kick the conference out of the cache + getConferenceMutex.Lock() + conferenceCache.Remove(confid) + getConferenceMutex.Unlock() + } + + // Just dump the whole conference property cache. + getConferencePropMutex.Lock() + conferencePropCache.Purge() + getConferencePropMutex.Unlock() + + // start a background job to remove all the conference data + background.Submit(func(ctx context.Context) { + start := time.Now() + // purge the conference data + for _, confid := range confids { + if confid > 0 { + err := backgroundPurgeConference(ctx, confid) + if err != nil { + log.Errorf("Conference purge(#%d) background job failed: %v", confid, err) + } + } + } + dur := time.Since(start) + log.Infof("conference deletion task completed in %v", dur) + }) + return nil +} + +func (*conferenceServiceVTable) OnUserJoinCommunity(context.Context, *sqlx.Tx, *Community, *User) error { + return nil +} + +func (*conferenceServiceVTable) OnUserLeaveCommunity(context.Context, *sqlx.Tx, *Community, *User) error { + return nil +} + /* AmGetConference returns a conference given its ID. * Parameters: * ctx - Standard Go context value. diff --git a/database/services.go b/database/services.go index cf12422..3123d6f 100644 --- a/database/services.go +++ b/database/services.go @@ -1,6 +1,6 @@ /* * Amsterdam Web Communities System - * Copyright (c) 2025 Erbosoft Metaverse Design Solutions, All Rights Reserved + * Copyright (c) 2025-2026 Erbosoft Metaverse Design Solutions, All Rights Reserved * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -17,15 +17,16 @@ import ( "sync" "git.erbosoft.com/amy/amsterdam/config" + "git.erbosoft.com/amy/amsterdam/util" lru "github.com/hashicorp/golang-lru" "github.com/jmoiron/sqlx" "gopkg.in/yaml.v3" ) -// ServiceVTable is a serioes of functions called for services on specific events. +// ServiceVTable is a series of functions called for services on specific events. type ServiceVTable interface { OnNewCommunity(context.Context, *sqlx.Tx, *Community) error - OnDeleteCommunity(context.Context, *sqlx.Tx, int32) error + OnDeleteCommunity(context.Context, *sqlx.Tx, int32, *util.WorkerPool) error OnUserJoinCommunity(context.Context, *sqlx.Tx, *Community, *User) error OnUserLeaveCommunity(context.Context, *sqlx.Tx, *Community, *User) error } @@ -37,7 +38,7 @@ func (*emptyServiceVTable) OnNewCommunity(context.Context, *sqlx.Tx, *Community) return nil } -func (*emptyServiceVTable) OnDeleteCommunity(context.Context, *sqlx.Tx, int32) error { +func (*emptyServiceVTable) OnDeleteCommunity(context.Context, *sqlx.Tx, int32, *util.WorkerPool) error { return nil } @@ -116,7 +117,7 @@ func init() { dom.byId["Profile"].vtable = &empty dom.byId["Admin"].vtable = &empty dom.byId["SysAdmin"].vtable = &empty - dom.byId["Conference"].vtable = &empty // TODO + dom.byId["Conference"].vtable = &(conferenceServiceVTable{}) dom.byId["Members"].vtable = &empty } @@ -247,14 +248,15 @@ func AmEstablishCommunityServices(ctx context.Context, tx *sqlx.Tx, c *Community * ctx - Standard Go context value. * tx - The transaction to use. * cid - The ID of the departing community. + * background - Pool in which background jobs can be submitted to clean up the database. * Returns: * Standard Go error status. */ -func AmDeleteCommunityServices(ctx context.Context, tx *sqlx.Tx, cid int32) error { +func AmDeleteCommunityServices(ctx context.Context, tx *sqlx.Tx, cid int32, background *util.WorkerPool) error { arr, err := AmGetCommunityServices(ctx, cid) if err == nil { for _, svc := range arr { - if err = svc.vtable.OnDeleteCommunity(ctx, tx, cid); err != nil { + if err = svc.vtable.OnDeleteCommunity(ctx, tx, cid, background); err != nil { break } } @@ -310,6 +312,15 @@ func AmOnUserLeaveCommunityServices(ctx context.Context, tx *sqlx.Tx, c *Communi return err } +/* AmTestService checks whether the community supports a service. + * Parameters: + * ctx - Standard Go context value. + * c - The community that is being tested. + * serviceId - The service ID to test. + * Returns: + * true if the community supports that service, false if not. + * Standard Go error status. + */ func AmTestService(ctx context.Context, c *Community, serviceId string) (bool, error) { arr, err := AmGetCommunityServices(ctx, c.Id) if err == nil { diff --git a/docs/MISSINGFUNCS.md b/docs/MISSINGFUNCS.md index 7e009c2..840a00e 100644 --- a/docs/MISSINGFUNCS.md +++ b/docs/MISSINGFUNCS.md @@ -6,7 +6,7 @@ _(italicized items can be deferred)_ - ~~Send out E-mails to topic subscribers when a post is made~~ - _Error handling: shift titles and templates for different error codes_ - ~~Find Posts~~ -- Services mechanism: Conference vtable +- ~~Services mechanism: Conference vtable~~ - ~~User creation: copy conference hotlists ~~ - _Calendar (top menu link)_ - _Chat (top menu link)_