Skip to content

Commit f1a6f43

Browse files
iahsfacebook-github-bot
authored andcommitted
SchemaRegistry::getTypeSystemDefinitionRefByUri
Summary: Enables accessing bundled schema data as TypeSystem nodes by uri, for definitions opted in using the `any` cpp2 compiler option, or statically for any definitions. Reviewed By: pranavtbhat Differential Revision: D75178792 fbshipit-source-id: 8f36fb30ef5def1a52c8bc65233fd154ff01f939
1 parent b3d41c2 commit f1a6f43

File tree

3 files changed

+93
-6
lines changed

3 files changed

+93
-6
lines changed

third-party/thrift/src/thrift/lib/cpp2/runtime/SchemaRegistry.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,16 @@ SchemaRegistry::getSyntaxGraphDefinitionNodeByUri(
102102
uri, type::ProgramId{data->programId}, data->data);
103103
}
104104

105+
std::optional<type_system::DefinitionRef>
106+
SchemaRegistry::getTypeSystemDefinitionRefByUri(
107+
const std::string_view uri) const {
108+
if (const auto* sgDef = getSyntaxGraphDefinitionNodeByUri(uri)) {
109+
std::lock_guard<folly::SharedMutex> wlock(typeSystemMutex_);
110+
return syntaxGraph_->asTypeSystemDefinitionRef(*sgDef);
111+
}
112+
return std::nullopt;
113+
}
114+
105115
} // namespace apache::thrift
106116

107117
#endif

third-party/thrift/src/thrift/lib/cpp2/runtime/SchemaRegistry.h

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
#ifdef THRIFT_SCHEMA_AVAILABLE
2222

2323
#include <unordered_set>
24+
#include <folly/SharedMutex.h>
2425
#include <folly/synchronization/RelaxedAtomic.h>
2526
#include <thrift/lib/cpp/util/EnumUtils.h>
27+
#include <thrift/lib/cpp2/dynamic/TypeSystem.h>
2628
#include <thrift/lib/cpp2/runtime/BaseSchemaRegistry.h>
2729
#include <thrift/lib/cpp2/schema/SyntaxGraph.h>
2830
#include <thrift/lib/cpp2/schema/detail/SchemaBackedResolver.h>
@@ -31,32 +33,49 @@
3133
namespace apache::thrift {
3234
namespace detail {
3335
template <typename T>
34-
struct SyntaxGraphNodeTag {
36+
struct NodeTag {
3537
using type = T;
3638
};
3739

3840
template <typename T>
3941
constexpr auto getSyntaxGraphNodeTypeFor() {
4042
if constexpr (is_thrift_service_tag_v<T>) {
41-
return SyntaxGraphNodeTag<syntax_graph::ServiceNode>{};
43+
return NodeTag<syntax_graph::ServiceNode>{};
4244
} else if constexpr (is_thrift_struct_v<T>) {
43-
return SyntaxGraphNodeTag<syntax_graph::StructNode>{};
45+
return NodeTag<syntax_graph::StructNode>{};
4446
} else if constexpr (is_thrift_union_v<T>) {
45-
return SyntaxGraphNodeTag<syntax_graph::UnionNode>{};
47+
return NodeTag<syntax_graph::UnionNode>{};
4648
} else if constexpr (is_thrift_exception_v<T>) {
47-
return SyntaxGraphNodeTag<syntax_graph::ExceptionNode>{};
49+
return NodeTag<syntax_graph::ExceptionNode>{};
4850
} else if constexpr (util::is_thrift_enum_v<T>) {
49-
return SyntaxGraphNodeTag<syntax_graph::EnumNode>{};
51+
return NodeTag<syntax_graph::EnumNode>{};
5052
} else {
5153
static_assert(folly::always_false<T>, "Unsupported Thrift type");
5254
}
5355
// It's unclear how to include typedefs and constants here.
5456
// TODO: interactions
5557
}
5658

59+
template <typename T>
60+
constexpr auto getTypeSystemNodeTypeFor() {
61+
if constexpr (is_thrift_struct_v<T>) {
62+
return NodeTag<type_system::StructNode>{};
63+
} else if constexpr (is_thrift_union_v<T>) {
64+
return NodeTag<type_system::UnionNode>{};
65+
} else if constexpr (util::is_thrift_enum_v<T>) {
66+
return NodeTag<type_system::EnumNode>{};
67+
} else {
68+
static_assert(folly::always_false<T>, "Unsupported Thrift type");
69+
}
70+
}
71+
5772
template <typename T>
5873
using SyntaxGraphNodeTypeFor =
5974
typename decltype(getSyntaxGraphNodeTypeFor<T>())::type;
75+
76+
template <typename T>
77+
using TypeSystemNodeTypeFor =
78+
typename decltype(getTypeSystemNodeTypeFor<T>())::type;
6079
} // namespace detail
6180
namespace test {
6281
struct SchemaTest;
@@ -88,6 +107,36 @@ class SchemaRegistry {
88107
.template as<detail::SyntaxGraphNodeTypeFor<T>>();
89108
}
90109

110+
/**
111+
* Gets TypeSystem node for given URI, or nullopt if not found.
112+
* Only types defined in a file with the `any` cpp2 compiler option enabled
113+
* can be found using this method.
114+
*/
115+
std::optional<type_system::DefinitionRef> getTypeSystemDefinitionRefByUri(
116+
const std::string_view uri) const;
117+
118+
/**
119+
* Gets TypeSystem node for given definition, or throws `std::out_of_range` if
120+
* not present in schema.
121+
*/
122+
template <typename T>
123+
type_system::DefinitionRef getTypeSystemDefinitionRef() const {
124+
const syntax_graph::DefinitionNode& sgNode = getDefinitionNode<T>();
125+
std::lock_guard<folly::SharedMutex> wlock(typeSystemMutex_);
126+
return syntaxGraph_->asTypeSystemDefinitionRef(sgNode);
127+
}
128+
129+
/**
130+
* Gets TypeSystem node for given definition, or throws `std::out_of_range` if
131+
* not present in schema. Returns most-derived type (e.g. StructNode) that
132+
* matches the template parameter.
133+
*/
134+
template <typename T>
135+
const detail::TypeSystemNodeTypeFor<T>& getTypeSystemNode() const {
136+
return getTypeSystemDefinitionRef<T>()
137+
.template asType<detail::TypeSystemNodeTypeFor<T>>();
138+
}
139+
91140
explicit SchemaRegistry(BaseSchemaRegistry& base);
92141
~SchemaRegistry();
93142

@@ -111,6 +160,9 @@ class SchemaRegistry {
111160

112161
std::unique_ptr<syntax_graph::SyntaxGraph> syntaxGraph_;
113162
syntax_graph::detail::IncrementalResolver* resolver_;
163+
// Synchronizes access to syntaxGraph_->asTypeSystem* methods, which are not
164+
// thread-safe.
165+
mutable folly::SharedMutex typeSystemMutex_;
114166

115167
friend struct test::SchemaTest;
116168
};

third-party/thrift/src/thrift/test/SchemaTest.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,4 +217,29 @@ TEST_F(SchemaTest, getSyntaxGraphDefinitionNodeByUri) {
217217
EXPECT_FALSE(getSyntaxGraphDefinitionNodeByUri(uriWithoutAny));
218218
}
219219

220+
TEST_F(SchemaTest, getTypeSystemDefinitionRef) {
221+
auto& registry = SchemaRegistry::get();
222+
223+
auto uri = "facebook.com/thrift/test/schema/Empty";
224+
225+
auto dynamicDefinitionRef = registry.getTypeSystemDefinitionRefByUri(uri);
226+
EXPECT_TRUE(dynamicDefinitionRef);
227+
228+
const type_system::StructNode& dynamicStructNode =
229+
dynamicDefinitionRef->asStruct();
230+
EXPECT_EQ(uri, dynamicStructNode.uri());
231+
232+
auto staticDefinitionRef =
233+
registry
234+
.getTypeSystemDefinitionRef<facebook::thrift::test::schema::Empty>();
235+
const type_system::StructNode& staticStructNode =
236+
staticDefinitionRef.asStruct();
237+
238+
const type_system::StructNode& directStructNode =
239+
registry.getTypeSystemNode<facebook::thrift::test::schema::Empty>();
240+
241+
EXPECT_EQ(&dynamicStructNode, &staticStructNode);
242+
EXPECT_EQ(&dynamicStructNode, &directStructNode);
243+
}
244+
220245
} // namespace apache::thrift::test

0 commit comments

Comments
 (0)