Skip to content

Commit 2893101

Browse files
tom-andersenwu-hui
andauthored
SessionToken persistence implementation (#13684)
Co-authored-by: Wu-Hui <[email protected]>
1 parent 96ca3cd commit 2893101

18 files changed

+594
-0
lines changed

Firestore/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# 11.3.0
22
- [changed] Improve efficiency of memory persistence when processing a large number of writes. (#13572)
3+
- [changed] Prepare Firestore cache to support session token.
34

45
# 11.2.0
56
- [fixed] Marked all public classes with only readonly properties as `Sendable` to address

Firestore/Example/Firestore.xcodeproj/project.pbxproj

Lines changed: 44 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* @license
3+
* Copyright 2024 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#ifndef FIRESTORE_CORE_SRC_LOCAL_GLOBALS_CACHE_H_
19+
#define FIRESTORE_CORE_SRC_LOCAL_GLOBALS_CACHE_H_
20+
21+
#include "Firestore/core/src/nanopb/byte_string.h"
22+
23+
using firebase::firestore::nanopb::ByteString;
24+
25+
namespace firebase {
26+
namespace firestore {
27+
namespace local {
28+
29+
/**
30+
* General purpose cache for global values.
31+
*
32+
* Global state that cuts across components should be saved here. Following are
33+
* contained herein:
34+
*
35+
* `sessionToken` tracks server interaction across Listen and Write streams.
36+
* This facilitates cache synchronization and invalidation.
37+
*/
38+
class GlobalsCache {
39+
public:
40+
virtual ~GlobalsCache() = default;
41+
42+
/**
43+
* Gets session token.
44+
*/
45+
virtual ByteString GetSessionToken() const = 0;
46+
47+
/**
48+
* Sets session token.
49+
*/
50+
virtual void SetSessionToken(const ByteString& session_token) = 0;
51+
};
52+
53+
} // namespace local
54+
} // namespace firestore
55+
} // namespace firebase
56+
57+
#endif // FIRESTORE_CORE_SRC_LOCAL_GLOBALS_CACHE_H_
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <string>
18+
19+
#include "Firestore/core/src/local/leveldb_globals_cache.h"
20+
#include "Firestore/core/src/local/leveldb_key.h"
21+
#include "Firestore/core/src/local/leveldb_persistence.h"
22+
23+
namespace firebase {
24+
namespace firestore {
25+
namespace local {
26+
27+
namespace {
28+
29+
const char* kSessionToken = "session_token";
30+
31+
}
32+
33+
LevelDbGlobalsCache::LevelDbGlobalsCache(LevelDbPersistence* db)
34+
: db_(NOT_NULL(db)) {
35+
}
36+
37+
ByteString LevelDbGlobalsCache::GetSessionToken() const {
38+
auto key = LevelDbGlobalKey::Key(kSessionToken);
39+
40+
std::string encoded;
41+
auto done = db_->current_transaction()->Get(key, &encoded);
42+
43+
if (!done.ok()) {
44+
return ByteString();
45+
}
46+
47+
return ByteString(encoded);
48+
}
49+
50+
void LevelDbGlobalsCache::SetSessionToken(const ByteString& session_token) {
51+
auto key = LevelDbGlobalKey::Key(kSessionToken);
52+
db_->current_transaction()->Put(key, session_token.ToString());
53+
}
54+
55+
} // namespace local
56+
} // namespace firestore
57+
} // namespace firebase
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef FIRESTORE_CORE_SRC_LOCAL_LEVELDB_GLOBALS_CACHE_H_
18+
#define FIRESTORE_CORE_SRC_LOCAL_LEVELDB_GLOBALS_CACHE_H_
19+
20+
#include "Firestore/core/src/local/globals_cache.h"
21+
22+
namespace firebase {
23+
namespace firestore {
24+
namespace local {
25+
26+
class LevelDbPersistence;
27+
28+
class LevelDbGlobalsCache : public GlobalsCache {
29+
public:
30+
/** Creates a new bundle cache in the given LevelDB. */
31+
explicit LevelDbGlobalsCache(LevelDbPersistence* db);
32+
33+
/**
34+
* Gets session token.
35+
*/
36+
ByteString GetSessionToken() const override;
37+
38+
/**
39+
* Sets session token.
40+
*/
41+
void SetSessionToken(const ByteString& session_token) override;
42+
43+
private:
44+
// The LevelDbGlobalsCache is owned by LevelDbPersistence.
45+
LevelDbPersistence* db_ = nullptr;
46+
};
47+
48+
} // namespace local
49+
} // namespace firestore
50+
} // namespace firebase
51+
52+
#endif // FIRESTORE_CORE_SRC_LOCAL_LEVELDB_GLOBALS_CACHE_H_

Firestore/core/src/local/leveldb_key.cc

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ namespace local {
3939
namespace {
4040

4141
const char* kVersionGlobalTable = "version";
42+
const char* kGlobalsTable = "globals";
4243
const char* kMutationsTable = "mutation";
4344
const char* kDocumentMutationsTable = "document_mutation";
4445
const char* kMutationQueuesTable = "mutation_queue";
@@ -159,6 +160,11 @@ enum ComponentLabel {
159160
*/
160161
DataMigrationName = 25,
161162

163+
/**
164+
* The name of a global.
165+
*/
166+
GlobalName = 26,
167+
162168
/**
163169
* A path segment describes just a single segment in a resource path. Path
164170
* segments that occur sequentially in a key represent successive segments in
@@ -245,6 +251,10 @@ class Reader {
245251
return ReadLabeledString(ComponentLabel::BundleId);
246252
}
247253

254+
std::string ReadGlobalName() {
255+
return ReadLabeledString(ComponentLabel::GlobalName);
256+
}
257+
248258
std::string ReadQueryName() {
249259
return ReadLabeledString(ComponentLabel::QueryName);
250260
}
@@ -718,6 +728,10 @@ class Writer {
718728
WriteLabeledString(ComponentLabel::TableName, table_name);
719729
}
720730

731+
void WriteGlobalName(absl::string_view global_name) {
732+
WriteLabeledString(ComponentLabel::GlobalName, global_name);
733+
}
734+
721735
void WriteBatchId(model::BatchId batch_id) {
722736
WriteLabeledInt32(ComponentLabel::BatchId, batch_id);
723737
}
@@ -1206,6 +1220,28 @@ bool LevelDbRemoteDocumentReadTimeKey::Decode(absl::string_view key) {
12061220
return reader.ok();
12071221
}
12081222

1223+
std::string LevelDbGlobalKey::KeyPrefix() {
1224+
Writer writer;
1225+
writer.WriteTableName(kGlobalsTable);
1226+
return writer.result();
1227+
}
1228+
1229+
std::string LevelDbGlobalKey::Key(absl::string_view global_name) {
1230+
Writer writer;
1231+
writer.WriteTableName(kGlobalsTable);
1232+
writer.WriteGlobalName(global_name);
1233+
writer.WriteTerminator();
1234+
return writer.result();
1235+
}
1236+
1237+
bool LevelDbGlobalKey::Decode(absl::string_view key) {
1238+
Reader reader{key};
1239+
reader.ReadTableNameMatching(kGlobalsTable);
1240+
global_name_ = reader.ReadGlobalName();
1241+
reader.ReadTerminator();
1242+
return reader.ok();
1243+
}
1244+
12091245
std::string LevelDbBundleKey::KeyPrefix() {
12101246
Writer writer;
12111247
writer.WriteTableName(kBundlesTable);

Firestore/core/src/local/leveldb_key.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,41 @@ class LevelDbNamedQueryKey {
768768
std::string name_;
769769
};
770770

771+
/**
772+
* A key in the globals table, storing the name of the global value.
773+
*/
774+
class LevelDbGlobalKey {
775+
public:
776+
/**
777+
* Creates a key prefix that points just before the first key of the table.
778+
*/
779+
static std::string KeyPrefix();
780+
781+
/**
782+
* Creates a key that points to the key for the given name of global value.
783+
*/
784+
static std::string Key(absl::string_view global_name);
785+
786+
/**
787+
* Decodes the given complete key, storing the decoded values in this
788+
* instance.
789+
*
790+
* @return true if the key successfully decoded, false otherwise. If false is
791+
* returned, this instance is in an undefined state until the next call to
792+
* `Decode()`.
793+
*/
794+
ABSL_MUST_USE_RESULT
795+
bool Decode(absl::string_view key);
796+
797+
/** The name that serves as identifier for global value for this entry. */
798+
const std::string& global_name() const {
799+
return global_name_;
800+
}
801+
802+
private:
803+
std::string global_name_;
804+
};
805+
771806
/**
772807
* A key in the index_configuration table, storing the index definition proto,
773808
* and the collection (group) it applies to.

Firestore/core/src/local/leveldb_persistence.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ LevelDbPersistence::LevelDbPersistence(std::unique_ptr<leveldb::DB> db,
126126
reference_delegate_ =
127127
absl::make_unique<LevelDbLruReferenceDelegate>(this, lru_params);
128128
bundle_cache_ = absl::make_unique<LevelDbBundleCache>(this, &serializer_);
129+
globals_cache_ = absl::make_unique<LevelDbGlobalsCache>(this);
129130

130131
// TODO(gsoltis): set up a leveldb transaction for these operations.
131132
target_cache_->Start();
@@ -250,6 +251,10 @@ LevelDbTargetCache* LevelDbPersistence::target_cache() {
250251
return target_cache_.get();
251252
}
252253

254+
LevelDbGlobalsCache* LevelDbPersistence::globals_cache() {
255+
return globals_cache_.get();
256+
}
257+
253258
LevelDbRemoteDocumentCache* LevelDbPersistence::remote_document_cache() {
254259
return document_cache_.get();
255260
}

Firestore/core/src/local/leveldb_persistence.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "Firestore/core/src/credentials/user.h"
2626
#include "Firestore/core/src/local/leveldb_bundle_cache.h"
2727
#include "Firestore/core/src/local/leveldb_document_overlay_cache.h"
28+
#include "Firestore/core/src/local/leveldb_globals_cache.h"
2829
#include "Firestore/core/src/local/leveldb_index_manager.h"
2930
#include "Firestore/core/src/local/leveldb_lru_reference_delegate.h"
3031
#include "Firestore/core/src/local/leveldb_migrations.h"
@@ -84,6 +85,8 @@ class LevelDbPersistence : public Persistence {
8485

8586
LevelDbBundleCache* bundle_cache() override;
8687

88+
LevelDbGlobalsCache* globals_cache() override;
89+
8790
LevelDbDocumentOverlayCache* GetDocumentOverlayCache(
8891
const credentials::User& user) override;
8992
LevelDbOverlayMigrationManager* GetOverlayMigrationManager(
@@ -154,6 +157,7 @@ class LevelDbPersistence : public Persistence {
154157
bool started_ = false;
155158

156159
std::unique_ptr<LevelDbBundleCache> bundle_cache_;
160+
std::unique_ptr<LevelDbGlobalsCache> globals_cache_;
157161
std::unordered_map<std::string, std::unique_ptr<LevelDbDocumentOverlayCache>>
158162
document_overlay_caches_;
159163
std::unordered_map<std::string,
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "Firestore/core/src/local/memory_globals_cache.h"
18+
19+
namespace firebase {
20+
namespace firestore {
21+
namespace local {
22+
23+
ByteString MemoryGlobalsCache::GetSessionToken() const {
24+
return session_token_;
25+
}
26+
27+
void MemoryGlobalsCache::SetSessionToken(const ByteString& session_token) {
28+
session_token_ = session_token;
29+
}
30+
31+
} // namespace local
32+
} // namespace firestore
33+
} // namespace firebase

0 commit comments

Comments
 (0)