Skip to content

Commit 5639c43

Browse files
committed
FLYPIE-270 Add record count to publish task
1 parent f80d81d commit 5639c43

4 files changed

Lines changed: 152 additions & 4 deletions

File tree

funcake_dags/scripts/index.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ rm lib/$INDEXER.rb.bak
2727
# grab list of items from designated aws bucket (creds are envvars), then index each item
2828
TEMPFILE=$(mktemp /tmp/index-output.XXXXXX)
2929
PUBLISH_TASK_REPORT=$AIRFLOW_HOME/dags/funcake_dags/scripts/publish_task_report.rb
30+
31+
solr_curl() {
32+
if [ -n "${SOLR_AUTH_USER:-}" ]; then
33+
curl -fsS -u "${SOLR_AUTH_USER}:${SOLR_AUTH_PASSWORD:-}" "$@"
34+
else
35+
curl -fsS "$@"
36+
fi
37+
}
38+
3039
report_and_cleanup() {
3140
rc=$?
3241
cat "$TEMPFILE" | ruby "$PUBLISH_TASK_REPORT" || true
@@ -70,3 +79,20 @@ do
7079
exit 1
7180
fi
7281
done
82+
83+
SOLR_BASE_URL="${FUNCAKE_OAI_SOLR_URL%/}"
84+
if ! solr_curl -X POST "${SOLR_BASE_URL}/update?commit=true" >/dev/null; then
85+
echo "ERROR: unable to commit Solr collection after publish"
86+
exit 1
87+
fi
88+
89+
SOLR_COUNT_RESPONSE=$(solr_curl "${SOLR_BASE_URL}/select?q=*:*&rows=0&wt=json")
90+
SOLR_PUBLISHED_COUNT=$(printf '%s' "$SOLR_COUNT_RESPONSE" | jq -r '.response.numFound // empty' 2>/dev/null || true)
91+
92+
if ! [[ "${SOLR_PUBLISHED_COUNT:-}" =~ ^[0-9]+$ ]]; then
93+
echo "ERROR: unable to parse published record count from Solr response"
94+
exit 1
95+
fi
96+
97+
export SOLR_PUBLISHED_COUNT
98+
echo "Published Record Count: $SOLR_PUBLISHED_COUNT"

funcake_dags/scripts/publish_task_report.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,11 @@ def collect_push_totals(output_lines)
77
.sum(&:to_i)
88
end
99

10-
puts "{ 'published': '#{collect_push_totals($stdin)}' }"
10+
def published_total(output_lines)
11+
solr_count = ENV["SOLR_PUBLISHED_COUNT"]
12+
return solr_count if solr_count&.match?(/\A\d+\z/)
13+
14+
collect_push_totals(output_lines)
15+
end
16+
17+
puts "{ 'published': '#{published_total($stdin)}' }"

tests/index_script_test.py

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,39 @@ def test_index_mode_with_empty_data_reports_missing_record_sets(self):
3030
self.assertNotIn("DATA: unbound variable", result.stdout + result.stderr)
3131
self.assertIn("ERROR: no record sets provided in DATA", result.stdout)
3232

33-
def _run_script(self, data: str | None = None):
33+
def test_publish_succeeds_when_solr_commit_and_count_succeed(self):
34+
result = self._run_script(
35+
data='["set1.xml"]',
36+
bundle_output="finished Traject::Indexer#process: 2 records in 0.1 seconds\n",
37+
solr_count="2",
38+
)
39+
40+
self.assertEqual(result.returncode, 0)
41+
self.assertIn("Published Record Count: 2", result.stdout)
42+
43+
def test_publish_fails_when_solr_commit_fails(self):
44+
result = self._run_script(
45+
data='["set1.xml"]',
46+
bundle_output="finished Traject::Indexer#process: 2 records in 0.1 seconds\n",
47+
curl_commit_exit=1,
48+
)
49+
50+
self.assertNotEqual(result.returncode, 0)
51+
self.assertIn("ERROR: unable to commit Solr collection after publish", result.stdout)
52+
53+
def _run_script(
54+
self,
55+
data: str | None = None,
56+
bundle_output: str = "",
57+
solr_count: str = "0",
58+
curl_commit_exit: int = 0,
59+
):
3460
tempdir = tempfile.mkdtemp()
3561
self.addCleanup(shutil.rmtree, tempdir, ignore_errors=True)
3662
tempdir_path = Path(tempdir)
3763
bin_dir = tempdir_path / "bin"
3864
bin_dir.mkdir()
65+
(tempdir_path / ".bashrc").write_text("", encoding="utf-8")
3966

4067
report_dir = tempdir_path / "dags" / "funcake_dags" / "scripts"
4168
report_dir.mkdir(parents=True)
@@ -53,8 +80,55 @@ def _run_script(self, data: str | None = None):
5380
""",
5481
)
5582
self._write_executable(bin_dir / "gem", "#!/usr/bin/env bash\nexit 0\n")
56-
self._write_executable(bin_dir / "bundle", "#!/usr/bin/env bash\nexit 0\n")
57-
self._write_executable(bin_dir / "aws", "#!/usr/bin/env bash\nexit 0\n")
83+
self._write_executable(
84+
bin_dir / "bundle",
85+
f"""#!/usr/bin/env bash
86+
if [ "$1" = "exec" ]; then
87+
printf %s {bundle_output!r}
88+
fi
89+
exit 0
90+
""",
91+
)
92+
self._write_executable(
93+
bin_dir / "aws",
94+
"""#!/usr/bin/env bash
95+
if [ "$1" = "s3" ] && [ "$2" = "presign" ]; then
96+
printf "http://example.test/presigned\\n"
97+
fi
98+
exit 0
99+
""",
100+
)
101+
self._write_executable(
102+
bin_dir / "curl",
103+
f"""#!/usr/bin/env bash
104+
args="$*"
105+
if [[ "$args" == *"/update?commit=true"* ]]; then
106+
exit {curl_commit_exit}
107+
fi
108+
if [[ "$args" == *"/select?q=*:*&rows=0&wt=json"* ]]; then
109+
printf '{{"response":{{"numFound":{solr_count}}}}}\\n'
110+
exit 0
111+
fi
112+
exit 0
113+
""",
114+
)
115+
self._write_executable(
116+
bin_dir / "jq",
117+
"""#!/usr/bin/env python3
118+
import json
119+
import sys
120+
121+
payload = json.load(sys.stdin)
122+
query = sys.argv[-1]
123+
if query == ".[]":
124+
for item in payload:
125+
print(item)
126+
elif query == ".response.numFound // empty":
127+
print(payload["response"]["numFound"])
128+
else:
129+
raise SystemExit(f"unsupported jq query: {query}")
130+
""",
131+
)
58132
self._write_executable(
59133
bin_dir / "ruby",
60134
"""#!/usr/bin/env bash

tests/publish_task_report_test.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import os
2+
import subprocess
3+
import unittest
4+
from pathlib import Path
5+
6+
7+
REPO_ROOT = Path(__file__).resolve().parents[1]
8+
SCRIPT_PATH = REPO_ROOT / "funcake_dags" / "scripts" / "publish_task_report.rb"
9+
10+
11+
class PublishTaskReportTest(unittest.TestCase):
12+
def test_falls_back_to_traject_batch_totals(self):
13+
result = subprocess.run(
14+
["ruby", str(SCRIPT_PATH)],
15+
input=(
16+
"finished Traject::Indexer#process: 2 records in 0.1 seconds\n"
17+
"finished Traject::Indexer#process: 3 records in 0.1 seconds\n"
18+
),
19+
text=True,
20+
capture_output=True,
21+
check=False,
22+
)
23+
24+
self.assertEqual(result.returncode, 0)
25+
self.assertEqual(result.stdout.strip(), "{ 'published': '5' }")
26+
27+
def test_prefers_solr_published_count_when_present(self):
28+
env = os.environ.copy()
29+
env["SOLR_PUBLISHED_COUNT"] = "4"
30+
31+
result = subprocess.run(
32+
["ruby", str(SCRIPT_PATH)],
33+
input="finished Traject::Indexer#process: 99 records in 0.1 seconds\n",
34+
text=True,
35+
capture_output=True,
36+
check=False,
37+
env=env,
38+
)
39+
40+
self.assertEqual(result.returncode, 0)
41+
self.assertEqual(result.stdout.strip(), "{ 'published': '4' }")

0 commit comments

Comments
 (0)