commands/list: implement new list command to the search channel

Closes #22
This commit is contained in:
Dmitriy Pleshevskiy 2022-10-24 18:06:28 +03:00 committed by pleshevskiy
parent 65dfd3136c
commit 529105d340
8 changed files with 198 additions and 17 deletions

View file

@ -2,7 +2,7 @@ version: '3'
services:
sonic:
image: valeriansaliou/sonic:v1.3.5
image: valeriansaliou/sonic:v1.4.0
ports:
- 36999:1491
volumes:

View file

@ -1,5 +1,20 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1662096612,
@ -18,22 +33,31 @@
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"utils": "utils"
"sonic-server": "sonic-server"
}
},
"utils": {
"sonic-server": {
"inputs": {
"flake-utils": [
"flake-utils"
],
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"lastModified": 1666618211,
"narHash": "sha256-kKeIM9dXUi8eYcvSomx8kqSqq9zmqMx4mE5wdpEZ6O8=",
"owner": "pleshevskiy",
"repo": "sonic",
"rev": "e83de87ebd2e29b210c8cc6e7dfed5d2f14a0d24",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"owner": "pleshevskiy",
"repo": "sonic",
"type": "github"
}
}

View file

@ -1,17 +1,26 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
utils.url = "github:numtide/flake-utils";
flake-utils.url = "github:numtide/flake-utils";
sonic-server = {
url = "github:pleshevskiy/sonic";
inputs.nixpkgs.follows = "nixpkgs";
inputs.flake-utils.follows = "flake-utils";
};
};
outputs = { self, nixpkgs, utils }:
utils.lib.eachDefaultSystem (system:
outputs = inputs @ { self, nixpkgs, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
pkgs = import nixpkgs {
inherit system;
overlays = [ inputs.sonic-server.overlays.default ];
};
in
{
devShell = pkgs.mkShell {
packages = with pkgs; [ cargo rustc rustfmt clippy rust-analyzer ];
packages = with pkgs; [ cargo rustc rustfmt clippy rust-analyzer sonic-server inetutils ];
RUST_SRC_PATH = pkgs.rustPlatform.rustLibSrc;
};
});

View file

@ -130,4 +130,35 @@ impl SearchChannel {
req: SuggestRequest,
);
);
init_command!(
/// Enumerates all words in an index.
///
/// Note: This method requires enabling the `search` feature and start
/// connection in Search mode.
///
/// ```rust,no_run
/// # use sonic_channel::*;
/// # fn main() -> result::Result<()> {
/// let search_channel = SearchChannel::start(
/// "localhost:1491",
/// "SecretPassword",
/// )?;
///
/// let result = search_channel.list(
/// ListRequest::new(Dest::col("search"))
/// )?;
/// dbg!(result);
///
/// let result = search_channel.list(
/// ListRequest::new(Dest::col("search")).limit(2)
/// )?;
/// dbg!(result);
/// # Ok(())
/// # }
/// ```
use ListCommand for fn list(
req: ListRequest,
);
);
}

View file

@ -11,6 +11,8 @@ mod pop;
#[cfg(feature = "ingest")]
mod push;
#[cfg(feature = "search")]
mod list;
#[cfg(feature = "search")]
mod query;
#[cfg(feature = "search")]
@ -29,9 +31,9 @@ pub(crate) use self::{
pub use self::{count::CountRequest, flush::FlushRequest, pop::PopRequest, push::PushRequest};
#[cfg(feature = "search")]
pub(crate) use self::{query::QueryCommand, suggest::SuggestCommand};
pub(crate) use self::{list::ListCommand, query::QueryCommand, suggest::SuggestCommand};
#[cfg(feature = "search")]
pub use self::{query::QueryRequest, suggest::SuggestRequest};
pub use self::{list::ListRequest, query::QueryRequest, suggest::SuggestRequest};
#[cfg(feature = "control")]
pub(crate) use trigger::TriggerCommand;

69
src/commands/list.rs Normal file
View file

@ -0,0 +1,69 @@
use super::StreamCommand;
use crate::misc::Dest;
use crate::protocol;
use crate::result::*;
/// Parameters for the `suggest` command.
#[derive(Debug)]
pub struct ListRequest {
/// Collection and bucket where we should enumerate all words in index.
pub dest: Dest,
/// Limit of result words.
pub limit: Option<usize>,
/// Offset of result words.
pub offset: Option<usize>,
}
impl ListRequest {
/// Creates a base suggest request.
pub fn new(dest: Dest) -> Self {
Self {
dest,
limit: None,
offset: None,
}
}
/// Set a limit for the request.
pub fn limit(mut self, limit: usize) -> Self {
self.limit = Some(limit);
self
}
/// Set an offset for the request.
pub fn offset(mut self, offset: usize) -> Self {
self.offset = Some(offset);
self
}
}
#[derive(Debug)]
pub struct ListCommand {
pub(crate) req: ListRequest,
}
impl StreamCommand for ListCommand {
type Response = Vec<String>;
fn request(&self) -> protocol::Request {
let dest = &self.req.dest;
protocol::Request::List {
collection: dest.collection().clone(),
bucket: dest
.bucket_opt()
.cloned()
.unwrap_or_else(|| String::from("default")),
limit: self.req.limit,
offset: self.req.offset,
}
}
fn receive(&self, res: protocol::Response) -> Result<Self::Response> {
if let protocol::Response::Event(protocol::EventKind::List, _id, words) = res {
Ok(words)
} else {
Err(Error::WrongResponse)
}
}
}

View file

@ -76,6 +76,17 @@ impl Protocol {
}
}
#[rustfmt::skip]
Request::List { collection, bucket, limit, offset } => {
write!(res, "LIST {} {}", collection, bucket)?;
if let Some(limit) = limit {
write!(res, " LIMIT({})", limit)?;
}
if let Some(offset) = offset {
write!(res, " OFFSET({})", offset)?;
}
}
Request::Trigger(triger_req) => match triger_req {
TriggerRequest::Consolidate => write!(res, "TRIGGER consolidate")?,
TriggerRequest::Backup(path) => {
@ -123,6 +134,7 @@ impl Protocol {
let event_kind = match segments.next() {
Some("SUGGEST") => Ok(EventKind::Suggest),
Some("QUERY") => Ok(EventKind::Query),
Some("LIST") => Ok(EventKind::List),
_ => Err(Error::WrongResponse),
}?;
@ -202,6 +214,7 @@ pub struct StartedPayload {
pub enum EventKind {
Suggest,
Query,
List,
}
//===========================================================================//
@ -223,6 +236,12 @@ pub enum Request {
word: String,
limit: Option<usize>,
},
List {
collection: String,
bucket: String,
limit: Option<usize>,
offset: Option<usize>,
},
Query {
collection: String,
bucket: String,

27
tests/list_command.rs Normal file
View file

@ -0,0 +1,27 @@
mod common;
use common::*;
const COLLECTION: &str = "Search";
#[test]
fn should_list_all_words() {
let bucket = "suggest_nearest";
let title = "Sweet Teriyaki Beef Skewers";
let dest = Dest::col_buc(COLLECTION, bucket);
let ingest_channel = ingest_start();
ingest_channel
.push(PushRequest::new(dest.clone().obj("1"), title))
.unwrap();
consolidate();
let search_channel = search_start();
match search_channel.list(ListRequest::new(dest.clone())) {
Ok(object_ids) => assert_eq!(object_ids, vec!["beef", "skewers", "sweet", "teriyaki"]),
Err(e) => unreachable!(),
}
flush_bucket(COLLECTION, bucket);
}