Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental interface demonstration #377

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 84 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 10 additions & 6 deletions buildpacks/ruby/src/layers/ruby_install_layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use bullet_stream::state::SubBullet;
use bullet_stream::Print;
use cache_diff::CacheDiff;
use commons::gemfile_lock::ResolvedRubyVersion;
use commons::layer::cache_buddy::CacheBuddy;
use commons::layer::cache_buddy::cache_layer_builder;
use flate2::read::GzDecoder;
use libcnb::data::layer_name;
use libcnb::layer::{EmptyLayerCause, LayerState};
Expand All @@ -39,11 +39,14 @@ pub(crate) fn handle(
mut bullet: Print<SubBullet<Stdout>>,
metadata: &Metadata,
) -> libcnb::Result<(Print<SubBullet<Stdout>>, LayerEnv), RubyBuildpackError> {
let layer_ref = CacheBuddy {
build: true,
launch: true,
}
.layer(layer_name!("ruby"), context, metadata)?;
let layer_ref = cache_layer_builder()
.build(true)
.launch(true)
.layer_name(layer_name!("ruby"))
.metadata(metadata)
.context(context)
.call()?;

match &layer_ref.state {
LayerState::Restored { cause } => {
bullet = bullet.sub_bullet(cause);
Expand Down Expand Up @@ -244,6 +247,7 @@ mod tests {
use super::*;
use crate::layers::shared::temp_build_context;
use bullet_stream::strip_ansi;
use commons::layer::cache_buddy::CacheBuddy;

/// If this test fails due to a change you'll need to
/// implement `TryMigrate` for the new layer data and add
Expand Down
1 change: 1 addition & 0 deletions commons/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ filetime = "0.2"
magic_migrate = "1.0"
toml = "0.8"
cache_diff = "1.0"
bon = "3.3.0"

[dev-dependencies]
filetime = "0.2"
Expand Down
64 changes: 64 additions & 0 deletions commons/src/layer/cache_buddy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,70 @@ pub struct CacheBuddy {
pub launch: bool,
}

type RestoredLayerFn<'a, M> = &'a dyn Fn(&M, &std::path::Path) -> (RestoredLayerAction, Meta<M>);
type InvalidMetaFn<'a, M> =
&'a dyn Fn(&libcnb::generic::GenericMetadata) -> (InvalidMetadataAction<M>, Meta<M>);

use bon::builder;

/// Creates a cached layer, potentially re-using a previously cached version.
///
/// <TODO>
#[builder]
pub fn cache_layer_builder<'a, B, M>(
/// Name of the layer
layer_name: LayerName,
/// Buildpack context
context: &BuildContext<B>,
/// Metadata to be used in the comparison
metadata: &M,

/// Write the provided metadata to disk
#[builder(default = true)]
update_metadata: bool,

/// Whether the layer is intended for build.
#[builder(default = true)]
build: bool,

/// Whether the layer is intended for launch.
#[builder(default = true)]
launch: bool,
/// Callback for when the metadata of a restored layer cannot be parsed as `M`.
///
/// Allows replacing the metadata before continuing (i.e. migration to a newer version) or
/// deleting the layer.
///
/// TODO default docs
#[builder(default = &invalid_metadata_action)]
on_invalid_metadata: InvalidMetaFn<'a, M>,

/// Callback when the layer was restored from cache to validate the contents and metadata.
/// Can be used to delete existing cached layers.
///
/// TODO default docs
on_restored_layer: Option<RestoredLayerFn<'a, M>>,
) -> libcnb::Result<LayerRef<B, Meta<M>, Meta<M>>, B::Error>
where
B: libcnb::Buildpack,
M: CacheDiff + TryMigrate + Serialize + Debug + Clone,
{
let layer_ref = context.cached_layer(
layer_name,
CachedLayerDefinition {
build,
launch,
invalid_metadata_action: on_invalid_metadata,
restored_layer_action: on_restored_layer
.unwrap_or(&|old: &M, _| restored_layer_action(old, metadata)),
},
)?;
if update_metadata {
layer_ref.write_metadata(metadata)?;
}
Ok(layer_ref)
}

impl CacheBuddy {
/// Writes metadata to a layer and returns a layer reference with info about prior cache state
///
Expand Down
Loading