Skip to content

Commit 09fc5ed

Browse files
authored
[core][feat] Use view to query the graph (#2101)
1 parent f3eacc6 commit 09fc5ed

File tree

19 files changed

+556
-202
lines changed

19 files changed

+556
-202
lines changed

fixcore/fixcore/cli/cli.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ def help_command() -> JsGen:
216216

217217
CLIArg = Tuple[CLICommand, Optional[str]]
218218
# If no sort is defined in the part, we use this default sort order
219+
# Note: changing the default sort order should be reflected in the graphdb search view (fix_view)
219220
DefaultSort = [Sort("/reported.kind"), Sort("/reported.name"), Sort("/reported.id")]
220221
# Default sort order for history searches
221222
HistorySort = [Sort("/changed_at"), Sort("/reported.kind"), Sort("/reported.name"), Sort("/reported.id")]

fixcore/fixcore/cli/command.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,37 +1464,35 @@ async def get_db(at: Optional[datetime], graph_name: GraphName) -> Tuple[GraphDB
14641464

14651465
return db_access.get_graph_db(graph_name), graph_name
14661466

1467-
async def load_query_model(db: GraphDB, graph_name: GraphName) -> QueryModel:
1467+
async def load_query_model(graph_name: GraphName) -> QueryModel:
14681468
model = await self.dependencies.model_handler.load_model(graph_name)
1469-
query_model = QueryModel(query, model, ctx.env)
1470-
await db.to_query(query_model) # only here to validate the query itself (can throw)
1471-
return query_model
1469+
return QueryModel(query, model, ctx.env)
14721470

14731471
async def explain_search() -> AsyncIterator[Json]:
14741472
db, graph_name = await get_db(at, current_graph_name)
1475-
query_model = await load_query_model(db, graph_name)
1473+
query_model = await load_query_model(graph_name)
14761474
explanation = await db.explain(query_model, with_edges)
14771475
yield to_js(explanation)
14781476

14791477
async def prepare() -> Tuple[CLISourceContext, AsyncIterator[Json]]:
14801478
db, graph_name = await get_db(at, current_graph_name)
14811479

1482-
query_model = await load_query_model(db, graph_name)
1480+
query_model = await load_query_model(graph_name)
14831481
count = ctx.env.get("count", "true").lower() != "false"
14841482
timeout = if_set(ctx.env.get("search_timeout"), duration)
1483+
consistent = ctx.env.get("consistent")
1484+
search_args = dict(with_count=count, timeout=timeout, consistent=consistent)
14851485
if history:
14861486
before = if_set(parsed.get("before"), lambda x: parse_time_or_delta(strip_quotes(x)))
14871487
after = if_set(parsed.get("after"), lambda x: parse_time_or_delta(strip_quotes(x)))
14881488
changes = [HistoryChange[strip_quotes(x)] for x in parsed.get("change", [])]
1489-
context = await db.search_history(
1490-
query_model, changes, before, after, with_count=count, timeout=timeout
1491-
)
1489+
context = await db.search_history(query_model, changes, before, after, **search_args)
14921490
elif query.aggregate:
1493-
context = await db.search_aggregation(query_model, with_count=count, timeout=timeout)
1491+
context = await db.search_aggregation(query_model, **search_args)
14941492
elif with_edges:
1495-
context = await db.search_graph_gen(query_model, with_count=count, timeout=timeout)
1493+
context = await db.search_graph_gen(query_model, **search_args)
14961494
else:
1497-
context = await db.search_list(query_model, with_count=count, timeout=timeout)
1495+
context = await db.search_list(query_model, **search_args)
14981496
cursor = context.cursor
14991497

15001498
# since we can not use context boundaries here,

fixcore/fixcore/core_config.py

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ def json(self) -> Json:
496496

497497

498498
@define()
499-
class GraphUpdateConfig(ConfigObject):
499+
class GraphConfig(ConfigObject):
500500
kind: ClassVar[str] = f"{FixCoreRoot}_graph_update_config"
501501
merge_max_wait_time_seconds: int = field(
502502
default=3600, metadata={"description": "Max waiting time to complete a merge graph action."}
@@ -517,6 +517,10 @@ class GraphUpdateConfig(ConfigObject):
517517
default=5,
518518
metadata={"description": "Number of parallel graph merge requests handled in parallel."},
519519
)
520+
use_view: bool = field(
521+
default=True,
522+
metadata={"description": "If true, the graph uses an efficient view to query the data."},
523+
)
520524

521525
def merge_max_wait_time(self) -> timedelta:
522526
return timedelta(seconds=self.merge_max_wait_time_seconds)
@@ -527,7 +531,7 @@ def abort_after(self) -> timedelta:
527531

528532
# Define rules to validate this config
529533
schema_registry.add(
530-
schema_name(GraphUpdateConfig),
534+
schema_name(GraphConfig),
531535
dict(
532536
merge_max_wait_time_seconds={"type": "integer", "min": 60},
533537
abort_after_seconds={"type": "integer", "min": 60},
@@ -609,7 +613,7 @@ class TimeSeriesConfig(ConfigObject):
609613
class CoreConfig(ConfigObject):
610614
api: ApiConfig
611615
cli: CLIConfig
612-
graph_update: GraphUpdateConfig
616+
graph: GraphConfig
613617
runtime: RuntimeConfig
614618
db: DatabaseConfig
615619
workflows: Dict[str, WorkflowConfig]
@@ -629,7 +633,7 @@ def no_scheduling(self) -> bool:
629633

630634
@property
631635
def editable(self) -> "EditableConfig":
632-
return EditableConfig(self.api, self.cli, self.graph_update, self.runtime, self.workflows, self.timeseries)
636+
return EditableConfig(self.api, self.cli, self.graph, self.runtime, self.workflows, self.timeseries)
633637

634638
def json(self) -> Json:
635639
return {FixCoreRoot: to_js(self.editable, strip_attr="kind")}
@@ -649,8 +653,8 @@ class EditableConfig(ConfigObject):
649653
factory=CLIConfig,
650654
metadata={"description": "CLI related properties."},
651655
)
652-
graph_update: GraphUpdateConfig = field(
653-
factory=GraphUpdateConfig,
656+
graph: GraphConfig = field(
657+
factory=GraphConfig,
654658
metadata={"description": "Properties for updating the graph."},
655659
)
656660
runtime: RuntimeConfig = field(
@@ -679,7 +683,7 @@ def config_model() -> List[Json]:
679683
dict(
680684
api={"schema": schema_name(ApiConfig), "allow_unknown": True},
681685
cli={"schema": schema_name(CLIConfig), "allow_unknown": True},
682-
graph_update={"schema": schema_name(GraphUpdateConfig), "allow_unknown": True},
686+
graph_update={"schema": schema_name(GraphConfig), "allow_unknown": True},
683687
runtime={"schema": schema_name(RuntimeConfig), "allow_unknown": True},
684688
workflows={
685689
"type": "dict",
@@ -774,7 +778,7 @@ def parse_config(
774778
custom_commands=commands_config,
775779
snapshots=snapshots_config,
776780
db=db,
777-
graph_update=ed.graph_update,
781+
graph=ed.graph,
778782
runtime=ed.runtime,
779783
workflows=ed.workflows,
780784
run=RunConfig(), # overridden for each run
@@ -790,23 +794,12 @@ def migrate_core_config(config: Json) -> Json:
790794
cfg = config.get(FixCoreRoot) or {}
791795
adapted = deepcopy(cfg)
792796

793-
# 2.2 -> 2.3: rename and toggle `analytics_opt_out` -> `usage_metrics`
794-
opt_out = value_in_path(cfg, "runtime.analytics_opt_out")
795-
usage = value_in_path(cfg, "runtime.usage_metrics")
796-
if opt_out is not None and usage is None:
797-
set_value_in_path(not opt_out, "runtime.usage_metrics", adapted)
798-
del_value_in_path(adapted, "runtime.analytics_opt_out")
799-
800-
# 3.0 -> 3.1: delete `api.ui_path`
801-
del_value_in_path(adapted, "api.ui_path")
802-
803-
# 3.5 -> 3.6: web_port -> https_port
804-
if web_port := value_in_path(cfg, "api.web_port"):
805-
set_value_in_path(web_port, "api.https_port", adapted)
806-
del_value_in_path(adapted, "api.web_port")
807-
808-
if value_in_path(cfg, "runtime.plantuml_server") == "http://plantuml.resoto.org:8080":
809-
set_value_in_path("https://plantuml.fix.security", "runtime.plantuml_server", adapted)
797+
# 4.0 -> 4.1: graph_update -> graph
798+
if graph_update := value_in_path(cfg, "graph_update"):
799+
log.info("Migrate fix.core config: rename graph_update to graph.")
800+
set_value_in_path(graph_update, "graph", adapted)
801+
set_value_in_path(True, "graph.use_view", adapted)
802+
del_value_in_path(adapted, "graph_update")
810803

811804
return {FixCoreRoot: adapted}
812805

0 commit comments

Comments
 (0)