github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/chat/storage/storage_delh.go (about)

     1  package storage
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/keybase/client/go/chat/globals"
     7  	"github.com/keybase/client/go/chat/utils"
     8  	"github.com/keybase/client/go/libkb"
     9  	"github.com/keybase/client/go/protocol/chat1"
    10  	"github.com/keybase/client/go/protocol/gregor1"
    11  	"golang.org/x/net/context"
    12  )
    13  
    14  type delhTracker struct {
    15  	globals.Contextified
    16  	utils.DebugLabeler
    17  }
    18  
    19  type delhTrackerEntry struct {
    20  	StorageVersion int `codec:"v"`
    21  	// The latest DeleteHistory upto value that has been applied locally
    22  	MaxDeleteHistoryUpto chat1.MessageID `codec:"ldhu"`
    23  	// The most ancient message that a new DeleteHistory could affect
    24  	MinDeletableMessage chat1.MessageID `codec:"em"`
    25  }
    26  
    27  const delhTrackerDiskVersion = 3
    28  
    29  func newDelhTracker(g *globals.Context) *delhTracker {
    30  	return &delhTracker{
    31  		Contextified: globals.NewContextified(g),
    32  		DebugLabeler: utils.NewDebugLabeler(g.ExternalG(), "DelhTracker", false),
    33  	}
    34  }
    35  
    36  func (t *delhTracker) makeDbKey(convID chat1.ConversationID, uid gregor1.UID) libkb.DbKey {
    37  	return libkb.DbKey{
    38  		Typ: libkb.DBChatBlocks,
    39  		Key: fmt.Sprintf("delh:%s:%s", uid, convID),
    40  	}
    41  }
    42  
    43  func (t *delhTracker) getEntry(ctx context.Context,
    44  	convID chat1.ConversationID, uid gregor1.UID) (delhTrackerEntry, Error) {
    45  
    46  	var blank delhTrackerEntry
    47  	var res delhTrackerEntry
    48  
    49  	dbKey := t.makeDbKey(convID, uid)
    50  	raw, found, err := t.G().LocalChatDb.GetRaw(dbKey)
    51  	if err != nil {
    52  		return res, NewInternalError(ctx, t.DebugLabeler, "GetRaw error: %s", err.Error())
    53  	}
    54  	if !found {
    55  		return res, MissError{}
    56  	}
    57  
    58  	err = decode(raw, &res)
    59  	if err != nil {
    60  		return blank, NewInternalError(ctx, t.DebugLabeler, "decode error: %s", err.Error())
    61  	}
    62  	switch res.StorageVersion {
    63  	case delhTrackerDiskVersion:
    64  		return res, nil
    65  	default:
    66  		// ignore other versions
    67  		return blank, MissError{}
    68  	}
    69  }
    70  
    71  func (t *delhTracker) setEntry(ctx context.Context,
    72  	convID chat1.ConversationID, uid gregor1.UID, entry delhTrackerEntry) Error {
    73  
    74  	entry.StorageVersion = delhTrackerDiskVersion
    75  	data, err := encode(entry)
    76  	if err != nil {
    77  		return NewInternalError(ctx, t.DebugLabeler, "encode error: %s", err.Error())
    78  	}
    79  
    80  	dbKey := t.makeDbKey(convID, uid)
    81  	err = t.G().LocalChatDb.PutRaw(dbKey, data)
    82  	if err != nil {
    83  		return NewInternalError(ctx, t.DebugLabeler, "PutRaw error: %s", err.Error())
    84  	}
    85  	t.Debug(ctx, "delhTracker.setEntry(%v, %+v)", convID, entry)
    86  	return nil
    87  }
    88  
    89  func (t *delhTracker) setMaxDeleteHistoryUpto(ctx context.Context,
    90  	convID chat1.ConversationID, uid gregor1.UID, msgid chat1.MessageID) Error {
    91  
    92  	// No need to use transaction here since the Storage class takes lock.
    93  
    94  	entry, err := t.getEntry(ctx, convID, uid)
    95  	switch err.(type) {
    96  	case nil:
    97  	case MissError:
    98  	default:
    99  		return err
   100  	}
   101  	entry.MaxDeleteHistoryUpto = msgid
   102  	return t.setEntry(ctx, convID, uid, entry)
   103  }
   104  
   105  func (t *delhTracker) setMinDeletableMessage(ctx context.Context,
   106  	convID chat1.ConversationID, uid gregor1.UID, msgid chat1.MessageID) Error {
   107  
   108  	entry, err := t.getEntry(ctx, convID, uid)
   109  	switch err.(type) {
   110  	case nil:
   111  	case MissError:
   112  	default:
   113  		return err
   114  	}
   115  	entry.MinDeletableMessage = msgid
   116  	return t.setEntry(ctx, convID, uid, entry)
   117  }
   118  
   119  // Set both values to msgid
   120  func (t *delhTracker) setDeletedUpto(ctx context.Context,
   121  	convID chat1.ConversationID, uid gregor1.UID, msgid chat1.MessageID) Error {
   122  
   123  	entry, err := t.getEntry(ctx, convID, uid)
   124  	switch err.(type) {
   125  	case nil:
   126  	case MissError:
   127  	default:
   128  		return err
   129  	}
   130  	entry.MaxDeleteHistoryUpto = msgid
   131  	entry.MinDeletableMessage = msgid
   132  	return t.setEntry(ctx, convID, uid, entry)
   133  }