Documentation
¶
Overview ¶
Package db implements the SQLite storage engine backing every stateful feature in tdlib. It opens a CGO-free modernc.org/sqlite database in WAL mode, runs embedded golang-migrate migrations, and exposes a typed key-value store, a crash-safe binlog of pending operations, and one domain method per file.
Index ¶
- type BinlogEntry
- type Chat
- type DB
- func (d *DB) AllocFileID(ctx context.Context) (id int64, err error)
- func (d *DB) BinlogAppend(ctx context.Context, tx *sql.Tx, opType string, payload []byte) (int64, error)
- func (d *DB) BinlogConfirm(ctx context.Context, id int64) error
- func (d *DB) BinlogConfirmBatch(ctx context.Context, ids []int64) error
- func (d *DB) BinlogReplay(ctx context.Context) ([]BinlogEntry, error)
- func (d *DB) Close() error
- func (d *DB) ConfirmPendingSend(ctx context.Context, binlogID, chatID, oldID, newID int64) (err error)
- func (d *DB) DB() *sql.DB
- func (d *DB) DeleteMessages(ctx context.Context, chatID int64, ids []int64) error
- func (d *DB) DeleteOption(ctx context.Context, name string) error
- func (d *DB) FailPendingSend(ctx context.Context, binlogID, chatID, msgID int64) (err error)
- func (d *DB) ForEachChannels(ctx context.Context, userID int64, ...) error
- func (d *DB) GetAllOptions(ctx context.Context) (map[string][]byte, error)
- func (d *DB) GetChannelAccessHash(ctx context.Context, _ int64, channelID int64) (int64, bool, error)
- func (d *DB) GetChannelPts(ctx context.Context, userID, channelID int64) (int, bool, error)
- func (d *DB) GetChat(ctx context.Context, id int64) (*Chat, error)
- func (d *DB) GetChatHistory(ctx context.Context, chatID, fromMessageID int64, offset, limit int) ([]*Message, error)
- func (d *DB) GetContacts(ctx context.Context) ([]*User, error)
- func (d *DB) GetFile(ctx context.Context, id int64) (*File, error)
- func (d *DB) GetFileByRemoteID(ctx context.Context, remoteID int64) (*File, error)
- func (d *DB) GetFileByUniqueID(ctx context.Context, uniqueID string) (*File, error)
- func (d *DB) GetFileReference(ctx context.Context, id int64) ([]byte, error)
- func (d *DB) GetMessage(ctx context.Context, chatID, id int64) (*Message, error)
- func (d *DB) GetMessageByRandomID(ctx context.Context, randomID int64) (*Message, error)
- func (d *DB) GetMessages(ctx context.Context, chatID int64, ids []int64) ([]*Message, error)
- func (d *DB) GetMyID(ctx context.Context) (int64, error)
- func (d *DB) GetOption(ctx context.Context, name string) ([]byte, error)
- func (d *DB) GetState(ctx context.Context, userID int64) (updates.State, bool, error)
- func (d *DB) GetUser(ctx context.Context, id int64) (*User, error)
- func (d *DB) GetUserAccessHash(ctx context.Context, _ int64, targetUserID int64) (int64, bool, error)
- func (d *DB) GetUsers(ctx context.Context, ids []int64) ([]*User, error)
- func (d *DB) InsertPendingSend(ctx context.Context, m *Message, opType string, payload []byte) (binlogID int64, err error)
- func (d *DB) KVDelete(ctx context.Context, ns KVNamespace, key string) error
- func (d *DB) KVGet(ctx context.Context, ns KVNamespace, key string) ([]byte, error)
- func (d *DB) KVGetAll(ctx context.Context, ns KVNamespace) (map[string][]byte, error)
- func (d *DB) KVSet(ctx context.Context, ns KVNamespace, key string, value []byte) error
- func (d *DB) ListDialogs(ctx context.Context) ([]*Chat, error)
- func (d *DB) SetChannelAccessHash(ctx context.Context, _ int64, channelID, accessHash int64) error
- func (d *DB) SetChannelPts(ctx context.Context, userID, channelID int64, pts int) error
- func (d *DB) SetContact(ctx context.Context, id int64, isContact, isMutual bool) error
- func (d *DB) SetDate(ctx context.Context, userID int64, date int) error
- func (d *DB) SetDateSeq(ctx context.Context, userID int64, date, seq int) error
- func (d *DB) SetFileReference(ctx context.Context, id int64, ref []byte) error
- func (d *DB) SetMyID(ctx context.Context, id int64) error
- func (d *DB) SetOption(ctx context.Context, name string, value []byte) error
- func (d *DB) SetPts(ctx context.Context, userID int64, pts int) error
- func (d *DB) SetQts(ctx context.Context, userID int64, qts int) error
- func (d *DB) SetSeq(ctx context.Context, userID int64, seq int) error
- func (d *DB) SetState(ctx context.Context, userID int64, s updates.State) error
- func (d *DB) SetUserAccessHash(ctx context.Context, _ int64, targetUserID, accessHash int64) error
- func (d *DB) SetUserStatus(ctx context.Context, id int64, kind int, expires, wasOnline int64) error
- func (d *DB) UpdateChatDraft(ctx context.Context, id int64, draftText string) error
- func (d *DB) UpdateChatLastMessage(ctx context.Context, id, lastMsgID, lastMsgDate int64) error
- func (d *DB) UpdateChatReadInbox(ctx context.Context, id, lastRead int64, unread int) error
- func (d *DB) UpdateChatReadOutbox(ctx context.Context, id, lastRead int64) error
- func (d *DB) UpsertChat(ctx context.Context, c *Chat) error
- func (d *DB) UpsertFile(ctx context.Context, f *File) error
- func (d *DB) UpsertMessage(ctx context.Context, m *Message) error
- func (d *DB) UpsertMessages(ctx context.Context, msgs []*Message) (err error)
- func (d *DB) UpsertUser(ctx context.Context, u *User) error
- type EncryptionKey
- type File
- type KVNamespace
- type Message
- type User
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BinlogEntry ¶
type BinlogEntry struct {
// ID is the auto-assigned row id; used to confirm the entry.
ID int64
// OpType is a short string tag identifying the operation kind, e.g.
// "send_message".
OpType string
// Payload is the serialised operation data (caller-chosen encoding).
Payload []byte
// CreatedAt is the wall-clock time the entry was appended.
CreatedAt time.Time
}
BinlogEntry is one pending operation that survives a crash. An entry is appended before the network call and confirmed (deleted) on success; unconfirmed entries are replayed on startup in ascending ID order.
type Chat ¶
type Chat struct {
ID int64
Type int
Title string
UserID int64
AccessHash int64
LastMessageID int64
LastMessageDate int64
Pinned bool
UnreadCount int
LastReadInboxMessageID int64
LastReadOutboxMessageID int64
DraftText string
InList bool
}
Chat is the chat row as stored by internal/db. It is self-contained (no root dependency); the root package converts to/from tdlib.Chat.
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB wraps a *sql.DB with the squirrel builder pre-configured for SQLite (question-mark placeholders). Domain methods are declared as receivers on this type, one file per domain.
func Open ¶
func Open(ctx context.Context, path string, key EncryptionKey, providers obs.Providers, logger log.Logger) (*DB, error)
Open opens (or creates) the SQLite database at path, applies embedded migrations, and returns a ready-to-use DB. When providers carry a real meter or tracer, the handle is instrumented via otelsql. The key parameter is reserved for at-rest encryption and is currently ignored.
The returned DB must be closed via DB.Close.
func (*DB) AllocFileID ¶
AllocFileID atomically increments and returns the next file-id sequence value.
func (*DB) BinlogAppend ¶
func (d *DB) BinlogAppend(ctx context.Context, tx *sql.Tx, opType string, payload []byte) (int64, error)
BinlogAppend writes a pending-operation entry. When tx is non-nil the insert runs inside it, so the domain change and the log entry commit or roll back together; pass nil to use the pool directly. It returns the new entry id.
func (*DB) BinlogConfirm ¶
BinlogConfirm deletes the entry with the given id after its network operation has succeeded.
func (*DB) BinlogConfirmBatch ¶
BinlogConfirmBatch deletes multiple entries in a single statement, used when one network response confirms several queued operations at once.
func (*DB) BinlogReplay ¶
func (d *DB) BinlogReplay(ctx context.Context) ([]BinlogEntry, error)
BinlogReplay returns all unconfirmed entries in ascending id order. It is called once on startup before accepting new operations.
func (*DB) ConfirmPendingSend ¶
func (d *DB) ConfirmPendingSend(ctx context.Context, binlogID, chatID, oldID, newID int64) (err error)
ConfirmPendingSend promotes a confirmed send: it remaps the message primary key from oldID to newID (clearing the pending state), removes the pending_sends mapping, and confirms (deletes) the binlog entry — atomically.
func (*DB) DB ¶
DB returns the raw *sql.DB for callers that need it (e.g. transactions that span a domain write and a binlog append).
func (*DB) DeleteMessages ¶
DeleteMessages removes messages from the cache; a no-op for absent ids.
func (*DB) DeleteOption ¶
DeleteOption removes the named option row; a no-op when absent.
func (*DB) FailPendingSend ¶
FailPendingSend marks a send as failed: it sets the message's sending_state to 2, removes the pending_sends mapping, and confirms the binlog entry (a terminal failure must not be replayed) — atomically.
func (*DB) ForEachChannels ¶
func (d *DB) ForEachChannels(ctx context.Context, userID int64, f func(ctx context.Context, channelID int64, pts int) error) error
ForEachChannels implements updates.StateStorage.
func (*DB) GetAllOptions ¶
GetAllOptions returns all rows from the option table as a map[name]value. Used by the option manager to load persisted state at startup.
func (*DB) GetChannelAccessHash ¶
func (d *DB) GetChannelAccessHash(ctx context.Context, _ int64, channelID int64) (int64, bool, error)
GetChannelAccessHash implements updates.ChannelAccessHasher.
func (*DB) GetChannelPts ¶
GetChannelPts implements updates.StateStorage.
func (*DB) GetChatHistory ¶
func (d *DB) GetChatHistory(ctx context.Context, chatID, fromMessageID int64, offset, limit int) ([]*Message, error)
GetChatHistory returns a page of cached messages for chatID, newest first. fromMessageID is the exclusive upper bound (zero = newest); offset shifts the window; limit is capped at 100.
func (*DB) GetContacts ¶
GetContacts returns all contact-flagged users ordered by id ascending.
func (*DB) GetFileByRemoteID ¶
GetFileByRemoteID returns the file with the given remote (document) id, or (nil, nil).
func (*DB) GetFileByUniqueID ¶
GetFileByUniqueID returns the file with the given unique id, or (nil, nil).
func (*DB) GetFileReference ¶
GetFileReference returns the stored file_reference bytes, or (nil, nil).
func (*DB) GetMessage ¶
GetMessage returns the cached message for (chatID, id), or (nil, nil).
func (*DB) GetMessageByRandomID ¶
GetMessageByRandomID returns the message bound to randomID via pending_sends, or (nil, nil) when there is no such pending send.
func (*DB) GetMessages ¶
GetMessages returns cached messages for ids within chatID; missing ones are omitted.
func (*DB) GetUserAccessHash ¶
func (d *DB) GetUserAccessHash(ctx context.Context, _ int64, targetUserID int64) (int64, bool, error)
GetUserAccessHash implements updates.UserAccessHasher.
func (*DB) InsertPendingSend ¶
func (d *DB) InsertPendingSend(ctx context.Context, m *Message, opType string, payload []byte) (binlogID int64, err error)
InsertPendingSend atomically records an optimistic outgoing message: it upserts the message row (with its pending sending_state and random_id), inserts the pending_sends mapping, and appends a binlog entry — all in one transaction so intent and state commit together. It returns the binlog id.
func (*DB) KVGet ¶
KVGet returns the value stored under (namespace, key), or (nil, nil) when the key does not exist.
func (*DB) ListDialogs ¶
ListDialogs returns all in-list chats ordered by (pinned DESC, date DESC).
func (*DB) SetChannelAccessHash ¶
SetChannelAccessHash implements updates.ChannelAccessHasher. It upserts the chats row's access_hash with the never-overwrite-with-zero rule (RFC 0009).
func (*DB) SetChannelPts ¶
SetChannelPts implements updates.StateStorage.
func (*DB) SetContact ¶
SetContact updates the contact flags for a user.
func (*DB) SetDateSeq ¶
SetDateSeq implements updates.StateStorage.
func (*DB) SetFileReference ¶
SetFileReference updates the file_reference bytes for id.
func (*DB) SetOption ¶
SetOption upserts a named option value. It demonstrates the domain-method pattern that subsequent RFCs follow, and is functionally complete for RFC 0007's core needs.
func (*DB) SetUserAccessHash ¶
SetUserAccessHash implements updates.UserAccessHasher. It delegates to the users-table upsert (which carries the never-overwrite-with-zero CASE).
func (*DB) SetUserStatus ¶
SetUserStatus updates only the status columns of a user, leaving every other column (notably access_hash and names) intact. It is a no-op for an unknown id.
func (*DB) UpdateChatDraft ¶
UpdateChatDraft persists the draft text.
func (*DB) UpdateChatLastMessage ¶
UpdateChatLastMessage updates the top message id and order key.
func (*DB) UpdateChatReadInbox ¶
UpdateChatReadInbox advances the inbox high-water mark and unread count.
func (*DB) UpdateChatReadOutbox ¶
UpdateChatReadOutbox advances the outbox high-water mark.
func (*DB) UpsertChat ¶
UpsertChat inserts or updates a chat header. The access_hash CASE never overwrites a stored non-zero hash with zero; in_list only ratchets up (a header upsert never removes a chat from the dialog list).
func (*DB) UpsertFile ¶
UpsertFile inserts or updates file metadata keyed by file_id.
func (*DB) UpsertMessage ¶
UpsertMessage inserts or updates a single message row.
func (*DB) UpsertMessages ¶
UpsertMessages inserts or updates a batch in one transaction.
func (*DB) UpsertUser ¶
UpsertUser inserts or updates the user row. The access_hash column is guarded by a CASE so a zero or min-user incoming value never overwrites a stored non-zero hash; phone is likewise preserved when the incoming value is empty.
type EncryptionKey ¶
type EncryptionKey []byte
EncryptionKey is reserved for future at-rest encryption (the TDLib DbKey analogue). Passing nil disables encryption; the parameter exists so the Open signature does not change when encryption lands.
type File ¶
type File struct {
FileID int64
RemoteID int64
UniqueID string
AccessHash int64
FileReference []byte
DCID int
LocalPath string
Size int64
DownloadedSize int64
IsDownloadingCompleted bool
IsUploadingCompleted bool
UploadedSize int64
}
File is the file row as stored by internal/db (self-contained; the root package converts to/from tdlib.File).
type KVNamespace ¶
type KVNamespace string
KVNamespace scopes key-value entries to avoid collisions between subsystems.
It lives in this package (not the root) so internal/db stays self-contained and the root package can import db without an import cycle.
const ( // KVNamespaceOptions stores account option values (RFC 0007). KVNamespaceOptions KVNamespace = "options" // KVNamespaceSession stores the gotd/td session bytes (RFC 0005). KVNamespaceSession KVNamespace = "session" // KVNamespaceUpdates stores update-state counters (RFC 0013). KVNamespaceUpdates KVNamespace = "updates" // KVNamespaceAuth stores the authorization state machine's persisted state // (RFC 0006). KVNamespaceAuth KVNamespace = "auth" // KVNamespaceUsers stores user-domain scalars such as my_id (RFC 0008). KVNamespaceUsers KVNamespace = "users" // KVNamespaceFiles stores the file-id sequence counter (RFC 0012). KVNamespaceFiles KVNamespace = "files" )
Key-value namespaces.
type Message ¶
type Message struct {
ChatID int64
ID int64
SenderID int64
Date int64
EditDate int64
IsOutgoing bool
ReplyToChatID int64
ReplyToMsgID int64
ContentKind int
ContentText string
SendingState int
RandomID int64
}
Message is the message row as stored by internal/db (self-contained; the root package converts to/from tdlib.Message).
type User ¶
type User struct {
ID int64
AccessHash int64
FirstName string
LastName string
Username string
Usernames []string
Phone string
StatusKind int
StatusExpires int64
StatusWasOnline int64
IsBot bool
IsContact bool
IsMutualContact bool
IsSelf bool
IsMin bool
}
User is the user row as stored by internal/db. It is a plain data type with no dependency on the root package, so internal/db stays self-contained; the root package converts between this and tdlib.User.